求和矩阵中的向量,在 C++ 中逐个元素
sum up vectors in a matrix, element by element in c++
C++中有没有一种简单的方法可以将组成矩阵的向量逐个元素相加?我的意思是,如果我有矩阵 M[3][4]
,我想要 sum[3]
包含以下组件的向量:
sum[0]=M[0][0]+M[1][0]+M[2][0]
sum[1]=M[0][1]+M[1][1]+M[2][1]
sum[2]=M[0][2]+M[1][2]+M[2][2]
我发现两个向量存在 ,我想将其扩展到许多向量,特别是组成矩阵 std::vector<vector<type> > M
的 std::vector<type>rows
,不知道-先验 M 的维数.
Is there a simple method in C++ that allows to sum up the vectors componing a matrix element by element? I mean, if I have the matrix M[3][4], I want the sum[3] vector with this components:
sum[0]=M[0][0]+M[1][0]+M[2][0]
sum[1]=M[0][1]+M[1][1]+M[2][1]
sum[2]=M[0][2]+M[1][2]+M[2][2]
很遗憾,C++标准库中没有简单的方法来添加
容器的元素按列排列。
有std::accumulate()
,但自然地,它会将行元素加在一起,而不是列元素,但我们可以通过遍历每一列来解决这个问题矩阵内的索引,并将元素一一相加:
#include <iostream>
#include <numeric>
#include <cstddef>
#include <vector>
// The below function assumes that all columns of your matrix have the same length
template <typename T>
std::vector<T> m_col_add(std::vector<std::vector<T>> const& mat) {
std::vector<T> res;
const auto column_size = mat[0].size();
for (size_t x = 0; x < column_size; ++x)
res.push_back(std::accumulate(mat.begin(), mat.end(), T{}, [x](T const& a, std::vector<T> const& row) {
return a + row[x];
}));
return res;
}
int main() {
std::vector<std::vector<int>> mat {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
auto res = m_col_add(mat);
for (auto const& elem : res)
std::cout << elem << " ";
}
输出:
15 18 21 24
或者,如果您在编译时已经知道行和列的大小并且使用的是 C++17 或更高版本,则可以使用 fold expressions and std::index_sequence<>
通过编译时扩展更快地添加元素:
#include <iostream>
#include <utility>
#include <cstddef>
#include <array>
template <size_t Column, typename T, size_t Rows, size_t Columns, size_t ...Sizes>
T m_col_add_impl2(std::index_sequence<Sizes...>, std::array<std::array<T, Columns>, Rows> const& mat) {
return (mat[Sizes][Column] + ...);
}
template <typename T, size_t Rows, size_t Columns, size_t ...Sizes>
std::array<T, Columns> m_col_add_impl1(std::index_sequence<Sizes...>, std::array<std::array<T, Columns>, Rows> const& mat) {
std::array<T, Columns> sum;
((sum[Sizes] = m_col_add_impl2<Sizes>(std::make_index_sequence<Rows>(), mat)), ...);
return sum;
}
template <typename T, size_t Rows, size_t Columns>
std::array<T, Columns> m_col_add(std::array<std::array<T, Columns>, Rows> const& mat) {
return m_col_add_impl1(std::make_index_sequence<Columns>(), mat);
}
int main() {
std::array mat {
std::array {1, 2, 3, 4},
std::array {5, 6, 7, 8},
std::array {9, 10, 11, 12}
};
auto res = m_col_add(mat);
for (auto const& elem : res)
std::cout << elem << " ";
}
输出:
15 18 21 24
您可以为向量定义 operator+=
,这样您就可以定义一个广义的 Sum
函数,该函数接收要求和的范围的开始和结束运算符,适用于具有任何值类型的迭代器+=
运算符类似于提供 +=
运算符的原始类型或(可能嵌套的)类型向量:
template<typename T>
std::vector<T>& operator+=(std::vector<T>& lhs, std::vector<T> const& rhs)
{
if (lhs.empty())
{
lhs = rhs; // first summand; 0 + x = x
}
else
{
for (size_t i = 0; i < lhs.size(); ++i)
{
lhs[i] += rhs.at(i); // component-wise add
}
}
return lhs;
}
// sum up elements in a given range
template<typename IteratorType>
typename std::iterator_traits<IteratorType>::value_type Sum(IteratorType summandBegin, IteratorType summandEnd)
{
typename std::iterator_traits<IteratorType>::value_type sum {}; // 0 or object created with default constructor depending on the type
while (summandBegin != summandEnd)
{
sum += *summandBegin;
++summandBegin;
}
return sum;
}
// sums the first count elements of a vector
template<typename T>
T PartialSum(std::vector<T> const& vec, size_t count)
{
assert(vec.size() >= count);
return Sum(vec.begin(), vec.begin() + count);
}
// logic for displaying
template<typename T>
std::ostream& operator<<(std::ostream& s, std::vector<T> const& vec)
{
s << '{';
for (auto& val : vec)
{
s << val << ", ";
}
s << '}';
return s;
}
int main(int argc, char *argv[]) {
std::vector<std::vector<std::vector<int>>> matrix { {{1, 2},{ 3, 4},{ 5, 6}},{{7, 8},{ 9, 10},{11, 12}},{{13, 14},{ 15, 16},{ 17, 18}}};
auto partialSum = PartialSum(matrix, 2);
std::cout << matrix << '\n' << partialSum << '\n';
std::cout << "\nSomething extra:\n";
std::vector<std::vector<std::string>> m2 = {{"Hell" , "Wo"} , {"o ", "rld!"}, {"foo", "bar"}};
auto message = PartialSum(m2, 2);
for (auto& msg : message)
{
std::cout << msg;
}
std::cout << '\n';
return 0;
}
C++中有没有一种简单的方法可以将组成矩阵的向量逐个元素相加?我的意思是,如果我有矩阵 M[3][4]
,我想要 sum[3]
包含以下组件的向量:
sum[0]=M[0][0]+M[1][0]+M[2][0]
sum[1]=M[0][1]+M[1][1]+M[2][1]
sum[2]=M[0][2]+M[1][2]+M[2][2]
我发现两个向量存在 std::vector<vector<type> > M
的 std::vector<type>rows
,不知道-先验 M 的维数.
Is there a simple method in C++ that allows to sum up the vectors componing a matrix element by element? I mean, if I have the matrix M[3][4], I want the sum[3] vector with this components:
sum[0]=M[0][0]+M[1][0]+M[2][0] sum[1]=M[0][1]+M[1][1]+M[2][1] sum[2]=M[0][2]+M[1][2]+M[2][2]
很遗憾,C++标准库中没有简单的方法来添加 容器的元素按列排列。
有std::accumulate()
,但自然地,它会将行元素加在一起,而不是列元素,但我们可以通过遍历每一列来解决这个问题矩阵内的索引,并将元素一一相加:
#include <iostream>
#include <numeric>
#include <cstddef>
#include <vector>
// The below function assumes that all columns of your matrix have the same length
template <typename T>
std::vector<T> m_col_add(std::vector<std::vector<T>> const& mat) {
std::vector<T> res;
const auto column_size = mat[0].size();
for (size_t x = 0; x < column_size; ++x)
res.push_back(std::accumulate(mat.begin(), mat.end(), T{}, [x](T const& a, std::vector<T> const& row) {
return a + row[x];
}));
return res;
}
int main() {
std::vector<std::vector<int>> mat {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
auto res = m_col_add(mat);
for (auto const& elem : res)
std::cout << elem << " ";
}
输出:
15 18 21 24
或者,如果您在编译时已经知道行和列的大小并且使用的是 C++17 或更高版本,则可以使用 fold expressions and std::index_sequence<>
通过编译时扩展更快地添加元素:
#include <iostream>
#include <utility>
#include <cstddef>
#include <array>
template <size_t Column, typename T, size_t Rows, size_t Columns, size_t ...Sizes>
T m_col_add_impl2(std::index_sequence<Sizes...>, std::array<std::array<T, Columns>, Rows> const& mat) {
return (mat[Sizes][Column] + ...);
}
template <typename T, size_t Rows, size_t Columns, size_t ...Sizes>
std::array<T, Columns> m_col_add_impl1(std::index_sequence<Sizes...>, std::array<std::array<T, Columns>, Rows> const& mat) {
std::array<T, Columns> sum;
((sum[Sizes] = m_col_add_impl2<Sizes>(std::make_index_sequence<Rows>(), mat)), ...);
return sum;
}
template <typename T, size_t Rows, size_t Columns>
std::array<T, Columns> m_col_add(std::array<std::array<T, Columns>, Rows> const& mat) {
return m_col_add_impl1(std::make_index_sequence<Columns>(), mat);
}
int main() {
std::array mat {
std::array {1, 2, 3, 4},
std::array {5, 6, 7, 8},
std::array {9, 10, 11, 12}
};
auto res = m_col_add(mat);
for (auto const& elem : res)
std::cout << elem << " ";
}
输出:
15 18 21 24
您可以为向量定义 operator+=
,这样您就可以定义一个广义的 Sum
函数,该函数接收要求和的范围的开始和结束运算符,适用于具有任何值类型的迭代器+=
运算符类似于提供 +=
运算符的原始类型或(可能嵌套的)类型向量:
template<typename T>
std::vector<T>& operator+=(std::vector<T>& lhs, std::vector<T> const& rhs)
{
if (lhs.empty())
{
lhs = rhs; // first summand; 0 + x = x
}
else
{
for (size_t i = 0; i < lhs.size(); ++i)
{
lhs[i] += rhs.at(i); // component-wise add
}
}
return lhs;
}
// sum up elements in a given range
template<typename IteratorType>
typename std::iterator_traits<IteratorType>::value_type Sum(IteratorType summandBegin, IteratorType summandEnd)
{
typename std::iterator_traits<IteratorType>::value_type sum {}; // 0 or object created with default constructor depending on the type
while (summandBegin != summandEnd)
{
sum += *summandBegin;
++summandBegin;
}
return sum;
}
// sums the first count elements of a vector
template<typename T>
T PartialSum(std::vector<T> const& vec, size_t count)
{
assert(vec.size() >= count);
return Sum(vec.begin(), vec.begin() + count);
}
// logic for displaying
template<typename T>
std::ostream& operator<<(std::ostream& s, std::vector<T> const& vec)
{
s << '{';
for (auto& val : vec)
{
s << val << ", ";
}
s << '}';
return s;
}
int main(int argc, char *argv[]) {
std::vector<std::vector<std::vector<int>>> matrix { {{1, 2},{ 3, 4},{ 5, 6}},{{7, 8},{ 9, 10},{11, 12}},{{13, 14},{ 15, 16},{ 17, 18}}};
auto partialSum = PartialSum(matrix, 2);
std::cout << matrix << '\n' << partialSum << '\n';
std::cout << "\nSomething extra:\n";
std::vector<std::vector<std::string>> m2 = {{"Hell" , "Wo"} , {"o ", "rld!"}, {"foo", "bar"}};
auto message = PartialSum(m2, 2);
for (auto& msg : message)
{
std::cout << msg;
}
std::cout << '\n';
return 0;
}