如何使用 std::acumulate 作为矩阵

How to use std::acumulate for matrix

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


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

int main()
{
    matrix mtx{5, 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::vector<std::vector<int>> 使用 std::accumulate,但我很好奇是否可以避免循环。另外我想知道最后一个参数是否可以。

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

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

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

int main() {
  Matrix mtx{5, 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 必须 return 一个值。

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

所以你最终得到这样的代码:

int sum{0};
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 mtx{3, 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 sum{0};
    std::ranges::for_each(jv, [&sum](auto n) { sum += ((n > 0) ? n : 0); });
    std::cout << "sum = " << sum << "\n";
}