скалярное произведение вектора & lt; вектор & lt; int & gt; & GT; по первому измерению

я имею

vector < vector < int > > data_mat ( 3, vector < int > (4) );
vector          < int >   data_vec ( 3                     );

где data_mat можно рассматривать как матрицу и data_vec в качестве вектора столбца, и я ищу способ вычисления внутреннего произведения каждого столбца data_mat с data_vecи сохранить его в другом vector < int > data_out (4),

Пример http://liveworkspace.org/code/2bW3X5%241 с помощью for_each а также transform, может использоваться для вычисления суммы столбца матрицы:

sum=vector<int> (data_mat[0].size());
for_each(data_mat.begin(), data_mat.end(),
[&](const std::vector<int>& c) {
std::transform(c.begin(), c.end(), sum.begin(), sum.begin(),
[](int d1, double d2)
{ return d1 + d2; }
);
}
);

Возможно ли аналогичным образом (или несколько другим способом, использующим функции STL) вычислить произведения точек столбцов матричных столбцов с вектором?

Проблема в том, что трюк ‘d2 = d1 + d2’ не работает здесь в случае с внутренним произведением столбца — если есть способ включить также d3, который бы ее решил (d3 = d3 + d1 * d2), но троичные функции, кажется, не существуют в transform,

4

Решение

На самом деле вы можете использовать свой существующий подход к сумме столбцов почти один к одному. Вам не нужен троичный 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;
});
});

РЕДАКТИРОВАТЬ: Хотя это уже обсуждалось в комментариях, и я понимаю (и понимаю) теоретическую природу вопроса, я все же включу предположение, что на практике динамический массив динамических массивов является отличным способом для представления такого структурно четко определенного 2D массив как матрица. Правильная матричная структура данных (которая хранит ее содержимое) с соответствующими операторами почти всегда является лучшим выбором. Но, тем не менее, из-за их универсальности вы все равно можете использовать стандартные библиотечные алгоритмы для работы с такой пользовательской структурой данных (возможно, даже позволяя типу матрицы предоставлять свои собственные итераторы).

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]