如何将 std::accumulate 用于矩阵

Posted

技术标签:

【中文标题】如何将 std::accumulate 用于矩阵【英文标题】:How to use std::acumulate for matrix 【发布时间】:2021-12-31 15:01:11 【问题描述】:
#include <iostream>
#include <numeric>
#include <vector>


using matrix = std::vector<std::vector<int>>;

int main()

    matrix mtx5, std::vector<int>(5);

    int sum = 0;
    for (const auto i : mtx) // can be avoided ? 
    sum += std::accumulate(i.begin(), i.end(), 0, 
        [](int a, int b)a > 0 ? a + b : a;);


我想将std::accumulate 用于std::vector&lt;std::vector&lt;int&gt;&gt;,但我很好奇是否可以避免循环。另外我想知道最后一个参数是否可以。

【问题讨论】:

您可以对每个外部向量使用accumulate,而函子将是您拥有的accumulate,基本上,累积在accumulate 中。 【参考方案1】:

根据您的 lambda,您似乎只想对正数项求和:

#include <iostream>
#include <numeric>
#include <vector>

using Number = int;
using Matrix = std::vector<std::vector<Number>>;

int main() 
  Matrix mtx5, std::vector<Number>(5, 1);

  Number sum_positives = std::accumulate(
      mtx.begin(), mtx.end(), Number(0), [](Number const acc, auto const &v) 
        return std::accumulate(
            v.begin(), v.end(), acc,
            [](Number const a, Number const b)  return b > 0 ? a + b : a; );
      );

  std::cout << sum_positives << std::endl;  // 25
  return 0;

不要忘记传递给 std::accumulate() 的 lambda 必须返回一个值。

【讨论】:

【参考方案2】:

C++20 范围的join_views 对此特别有用,因为它们允许您将矩阵展平为向量。

所以你最终会得到如下代码:

int sum0;
auto jv std::ranges::join_view(mtx) ;  // flatten mtx into a list of ints
std::ranges::for_each(jv, [&sum](auto n)  sum += ((n > 0) ? n : 0); );

不幸的是,范围'accumulate 直到 C++23 才可用:

auto sum std::ranges::accumulate(jv, 0, [](auto total, auto n)  return total + ((n > 0) ? n : 0); ) ;

对于用[-100, 100] 之间的随机数填充矩阵的完整样本:

[Demo]

#include <algorithm>  // for_each
#include <iostream>  // cout
#include <random>  // default_random_engine, uniform_int_distribution
#include <ranges>  // for_each, join_view
#include <vector>

using matrix = std::vector<std::vector<int>>;

int main()

    matrix mtx3, std::vector<int>(3);

    // Fill matrix with random values between [-100, 100]
    std::default_random_engine re std::random_device() ;
    std::uniform_int_distribution<int> dist -100, 100 ;
    std::for_each(std::begin(mtx), std::end(mtx),
        [&dist, &re](auto& row) 
            std::for_each(std::begin(row), std::end(row),
                [&dist, &re](auto& n)  n = dist(re); 
            );
        
    );

    auto jv std::ranges::join_view(mtx) ;  // flatten mtx into a list of ints
    
    // Print matrix
    std::cout << "mtx = ";
    std::ranges::for_each(jv, [](auto n)  std::cout << n << " "; );
    std::cout << "\n";

    // Sum all positive values in the matrix    
    int sum0;
    std::ranges::for_each(jv, [&sum](auto n)  sum += ((n > 0) ? n : 0); );
    std::cout << "sum = " << sum << "\n";

【讨论】:

以上是关于如何将 std::accumulate 用于矩阵的主要内容,如果未能解决你的问题,请参考以下文章

std::accumulate的用法(转)

C++ STL应用与实现86: 如何使用std::accumulate

std::accumulate

性能差异:std :: accumulate vs std :: inner_product vs Loop

STL的accumulate用法

std::string,std::vector,std::accumulate注意事项