簡體   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