実際、既存の列合計アプローチをほぼ1対1で使用できます。std::transform
行列行を合計する前にスケーリングする係数は、列ベクトルからの行値であり、行列行と一緒に繰り返されるため、各行で一定であるため、内部ループとして3値は必要ありません。アウターstd::for_each
。
したがって、必要なのは、行列の行を反復処理し、各完全な行に列ベクトルの対応する値を掛けて、そのスケーリングされた行を合計ベクトルに追加することです。ただし、残念ながら、このためにstd::for_each
は、行列の行と列ベクトルの行の2つの範囲を同時に繰り返す関数が必要になります。これを実現するには、通常の単項std::for_each
を使用し、追加のイテレータを使用して、列ベクトルに対して手動で反復を実行します。
std::vector<int> sum(data_mat[0].size());
auto vec_iter = data_vec.begin();
std::for_each(data_mat.begin(), data_mat.end(),
[&](const std::vector<int>& row) {
int vec_value = *vec_iter++; //manually advance vector row
std::transform(row.begin(), row.end(), sum.begin(), sum.begin(),
[=](int a, int b) { return a*vec_value + b; });
});
内部での追加の手動反復std::for_each
は、実際には標準ライブラリアルゴリズムの慣用的な使用ではありませんが、残念ながら、使用できるバイナリはありませんstd::for_each
。
もう1つのオプションはstd::transform
、外部ループ(2つの範囲で反復可能)として使用することですが、返す各外部反復で実際には単一の値を計算しないため、外部ラムダからダミー値を返すだけで済みます。ある種のダミー出力イテレータを使用して破棄します。それも最もクリーンな解決策ではありません:
//output iterator that just discards any output
struct discard_iterator : std::iterator<std::output_iterator_tag,
void, void, void, void>
{
discard_iterator& operator*() { return *this; }
discard_iterator& operator++() { return *this; }
discard_iterator& operator++(int) { return *this; }
template<typename T> discard_iterator& operator=(T&&) { return *this; }
};
//iterate over rows of matrix and vector, misusing transform as binary for_each
std::vector<int> sum(data_mat[0].size());
std::transform(data_mat.begin(), data_mat.end(),
data_vec.begin(), discard_iterator(),
[&](const std::vector<int>& row, int vec_value) {
return std::transform(row.begin(), row.end(),
sum.begin(), sum.begin(),
[=](int a, int b) {
return a*vec_value + b;
});
});
編集:これはすでにコメントで議論されており、質問の理論的性質を理解しています(そして感謝しています)が、実際には動的配列の動的配列はそのような構造的にうまく表現するためのひどい方法であるという提案を含めます-行列のように定義された2D配列。適切な演算子を使用した適切な行列データ構造(コンテンツを連続して格納する)は、ほとんどの場合、より適切な選択です。ただし、その汎用性により、このようなカスタムデータ構造を操作するための標準ライブラリアルゴリズムを使用できます(おそらく、行列型に独自のイテレータを提供させることによっても)。