【问题标题】:Usage of STL algorithm functions on more then one dimensional containers在多于一维的容器上使用 STL 算法函数
【发布时间】:2020-07-06 13:40:18
【问题描述】:

我有一个简单的结构

struct Point
{
    Point(int x, int y)
        : x(x)
        , y(y)
    {}
    
    int x, y;
};

还有一个二维向量(也可以是三维向量或更多)

std::vector<std::vector<Point>> v(10, std::vector<Point>(10, Point(3, 4)));

我想知道所有 x 值的摘要。 我可以使用 std::accumulate ,它看起来像

int sum = std::accumulate(v.begin(), v.end(), 0, [](int init, const auto& vec)
  {
    return init + std::accumulate(vec.begin(), vec.end(), 0, [](int init, Point p)
    {
        return init + p.x;
    });
  });

或者我可以为

写一个简单的double
for (const auto& vec : v)
{
    for (const auto& p : vec)
    {
        sum += p.x;
    }
}

而且它看起来更具可读性(imo)。 我应该改变什么以使 std::accumulate 的使用具有更好的可读性?或者在这种情况下不适用。当您拥有多于一维的容器时,是否普遍适用 STL?

【问题讨论】:

  • 多维std::vectors 效率有点低,最好使用带有为您实现索引的包装类的单维向量,这也将简化标准算法的使用
  • 拥有多维容器只是表示数据的一种方式。属于一起的 IMO 数据通常应该在同一个容器中。如果您需要该数据的多维表示,您可以这样做并且仍然将数据存储在单个向量中。
  • 我应该改变什么以使 std::accumulate 的使用具有更好的可读性? 恕我直言,没什么。我知道那里有建议说不要使用原始循环,但恕我直言,基于范围的 for 循环不是原始循环。它扩展到使用迭代器,变量是实际的当前元素,因此您使用的项目没有错误。在这种情况下,它们会使代码更加简洁易懂。
  • 是的,使用 C++11 标准,基于范围的 for 循环似乎是最好的方法。但是来自 C++20 的 range-v3 看起来很棒,让它成为带有“累积”字样的单行。

标签: c++ stl


【解决方案1】:

如果您考虑现在的 STL,那么嵌套的 range-for 循环可能是最易读的(尽管它仍然是主观的)。

但是,我非常提倡不要使用 range-for 循环,除非您需要 transformfor_each。如果代码是accumulate,那么你应该写一个accumulate

这就是我今天在 range-v3 的帮助下编写此代码的方式。不久之后,STL 将让您编写可读的代码。

namespace rs = ranges;
namespace rv = ranges::views;

int sum = rs::accumulate(v | rv::join, 0, std::plus{}, &Point::x);

这是demo

【讨论】:

  • 天哪。我无法想象它可以用“积累”一词写在一行中。 Range-v3 是朝着清晰易读的代码迈出的一大步。如果需要累积三个维度向量 | rv::join 应该被添加。这太不可思议了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
相关资源
最近更新 更多