#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;});
}
I want to use std::accumulate
for std::vector<std::vector<int>>
but I am curious if I can avoid the loop. Also I want to know if the last argument is ok.
CodePudding user response:
Based on your lambda, looks like you want to just sum the positive entries:
#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;
}
Don't forget that the lambda you pass to std::accumulate()
must return a value.
CodePudding user response:
C 20 ranges' join_view
s are especially useful for this, since they allow you to flatten a matrix into a vector.
So you end up with a code like:
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; });
For a full sample filling the matrix with random numbers between [-100, 100]
:
#include <algorithm> // fill, for_each
#include <iostream> // cout
#include <random>
#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";
}