На самом деле вы можете использовать существующий подход к сумме столбцов почти один к одному. Вам не нужен троичный std::transform
в качестве внутреннего цикла, потому что коэффициент, с которым вы масштабируете строки матрицы перед их суммированием, является постоянным для каждой строки, поскольку это значение строки из вектора-столбца, которое повторяется вместе со строками матрицы и, таким образом, внешний std::for_each
.
Итак, что нам нужно сделать, это перебрать строки матрицы и умножить каждую полную строку на соответствующее значение в векторе-столбце и добавить эту масштабированную строку к вектору суммы. Но, к сожалению, для этого нам понадобится функция std::for_each
, которая одновременно перебирает два диапазона, строки матрицы и строки вектора-столбца. Для этого мы могли бы использовать обычный унарный 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
, который мы могли бы использовать.
Другим вариантом было бы использовать std::transform
в качестве внешнего цикла (который может выполнять итерацию по двум диапазонам), но на самом деле мы не вычисляем одно значение в каждой внешней итерации для возврата, поэтому нам нужно будет просто вернуть какое-то фиктивное значение из внешней лямбды. и выбросьте его, используя какой-нибудь фиктивный итератор вывода. Это тоже было бы не самым чистым решением:
//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;
});
});
EDIT: Хотя это уже обсуждалось в комментариях, и я понимаю (и ценю) теоретическую природу вопроса, я все же включу предположение, что на практике динамический массив динамических массивов — это ужасный способ для представления такого структурно четко определенного двумерного массива, как матрица. Правильная матричная структура данных (которая хранит свое содержимое непрерывно) с соответствующими операторами почти всегда является лучшим выбором. Но, тем не менее, из-за их универсальности вы все равно можете использовать стандартные алгоритмы библиотеки для работы с такой пользовательской структурой данных (возможно, даже позволив матричному типу предоставлять свои собственные итераторы).
person
Christian Rau
schedule
06.03.2013
inner_product
? - person Peter Wood   schedule 05.03.2013{ d3 + d1 * d2; }
в преобразовании. - person alle_meije   schedule 05.03.2013vector<vector>
вздор, а не общий подходtransform
или<algorithm>
. И, как уже было сказано, идея решения таких задач, как та, что в вопросе, только с помощью алгоритмов STL, действительно хороша, даже если в данном конкретном случае имеет только теоретическое значение. - person Christian Rau   schedule 06.03.2013