繁体   English   中英

是否存在std中的折叠类似算法(或者失败:boost)?

[英]Is there a fold like algorithm in std (or failing that: boost) available?

一个非常简单的例子是乘法 - 假设我有一个向量:

std::vector<int> ints = {1,2,3,4};

使用简单的方法我可以使用std::accumulate (或std::reduce ),它看起来像这样:

int result = std::accumulate(ints.begin(), ints.end(), int{}, [](const int &a, const int &b){return a*b;});

但由于初始值为零 - 结果也变为零(对于这种特定情况,我可以解决的一种方法是将'1'作为初始值)。

我宁愿使用一种算法来完成上述操作但没有初始值'副作用'(即只是乘以向量中的数字)。

在字符串处理中经常遇到类似的问题,其中必须元素之间插入分隔符。

你所谈论的内容可以被重新定义为在你的范围的最后N-1个元素上accumulate的概括,第一个元素是初始值。

所以你可以写:

std::accumulate(std::next(std::begin(ints)), std::end(ints), *std::begin(ints), OP);

你必须假设ints是非空的,这提出了我的要点:当范围为空时,假设的标准函数应该返回什么? 它的结果应该是不确定的吗? 那是明智的吗?

积累回避这个问题,通过按照它的方式做事提供了大量的灵活性。 我认为这是件好事。

结合在整个范围内为您的操作简单地提供适当的初始值(如1的能力,我不相信标准中需要这个假设的替代方案。

也许很难为它提出两个名称来反映已经非对称命名的“累积”和“减少”。


template <class InputIt, class T, class BinaryOperation>
T fold_if_you_really_want_to(InputIt first, InputIt last, BinaryOperation op)
{
    // UB if range is empty. Whatevs.
    T init = *first;
    return std::accumulate(++first, last, std::move(init), std::move(op));
}

......或者类似的东西。 请注意,这必然会复制第一个元素; 你可以避免这种情况,如果你不是像我一样调用std::accumulate而不是懒惰。 😊

除了Orbit答案中的@Lightness Races之外,还要考虑Haskell中的情况:对于像你描述的那样(最突出地搜索列表中的最大元素),Haskell提供了foldl1foldr1函数,它们对集合执行折叠,隐含地将第一个值作为初始值。 是的,对于空列表,这没有任何意义,因此对于此问题,您必须提供至少包含一个元素的列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM