如何使用 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]
:
之间的随机数填充矩阵的完整样本
#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";
}
#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]
:
#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";
}