[英]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提供了foldl1
和foldr1
函數,它們對集合執行折疊,隱含地將第一個值作為初始值。 是的,對於空列表,這沒有任何意義,因此對於此問題,您必須提供至少包含一個元素的列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.