Скалярное произведение вектора <vector <int>> над первым измерением

Я имею

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,

1 ответ

Решение

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

Другие вопросы по тегам