C++ accumulate函數用法詳解

2020-07-16 10:04:32
我們已經介紹過 accumulate() 演算法的基本版本,可以用 + 運算子求出元素序列的和。前兩個引數是定義序列的輸入疊代器,第三個引數是和的初值;第三個引數的型別決定了返回值的型別。第二個版本的第 4 個引數是定義應用到總數和元素之間的二元函數物件。這時,我們在必要時可以定義自己的加法運算。例如:
std::vector<int> values {2, 0, 12, 3, 5, 0, 2, 7, 0, 8};
int min {3};
auto sum = std::accumulate(std::begin(values), std::end(values), 0, [min] (int sum, int v)
{
    if(v < min)
        return sum;
    return sum + v;
});
std::cout << "The sum of the elements greater than " << min-1<<"is " << sum << std::endl;  // 35
這裡忽略了值小於 3 的元素。這個條件可以盡可能複雜,因此,我們能夠求出指定範圍內的元素之和。這個運算並不一定要是加法,可以是任何不修改運算元或不使定義範圍的疊代器無效的運算。例如,為數值元素定義的乘法運算函數會生成元素的乘積,只要初值為 1。實現浮點元素除法的函數會生成元素乘積的倒數,只要初值為 1。下面展示了如何生成元素的乘積:
std::vector<int> values {2, 3, 5, 7, 11, 13};
auto product = std::accumulate(std::begin(values), std::end(values), 1, std::multiplies<int>()); // 30030
這裡用來自於 functional 標頭檔案的函數作為第 4 個引數。如果有值為 0 的元素,可以像上一個程式碼段中的 lambda 表示式那樣忽略它們。

string 類支援加法,因此可以將 accumulate() 應用到 string 物件的序列上:
std:: vector<string> numbers {"one", "two", "three", "four", "five","six", "seven","eight", "nine","ten"};
auto s = std::accumulate(std::begin(numbers), std::end(numbers), string{},[](strings str, string& element)
{
    if (element[0] == 't')
        return str +' '+ element;
    return str;
}); // Result: " two three ten"
這段程式碼連線了以開頭的 string 物件,並用空格將它們隔開。acumulate() 演算法得到的結果可能和它所應用的序列中的元素型別不同:
std::vector<int> numbers {1, 2, 3, 10, 11, 12};
auto s = std::accumulate(std::begin(numbers), std::end(numbers),string {"The numbers are"},[](strings str, int n){ return str + " : " + std::to_string(n);});
std::cout << s << std::endl;//Output: The numbers are: 1: 2: 3: 10: 11: 12
lambda 表示式使用的 to_string() 函數會返回一個數值引數的 string 形式,所以應用 accumulate() 到這裡的整數序列會返回注釋中顯示的 string。