Накапливать каждый второй элемент в векторе C ++ - PullRequest
0 голосов
/ 31 октября 2019

Я хочу иметь возможность накапливать любую другую пару элементов в векторе, используя накопление. Я попробовал следующее без особого успеха, возвращая ошибку для непустого, ненулевого вектора

return std::accumulate(vec.begin(), vec.end(), 0,
      [&](int runningSum, int first, int second)
      {return runningSum = runningSum + min(first, second);});

, который теперь я понимаю, что, вероятно, не получит минимум между парами. Например, если у меня есть

vector<int> vec = {1,4,2,3} 

, я хочу вернуть 0 + мин (1, 4) + мин (2, 3).

С другой стороны, есть ли какой-либо веб-сайт смного примеров этих встроенных модулей STL? Я нахожу примеры в Интернете далеко и мало. Я действительно хочу увидеть силу накопления и привыкнуть к ней.

Ответы [ 2 ]

3 голосов
/ 31 октября 2019

std::accumulate() не позволяет использовать предикат с 3 параметрами, только 2 параметра - текущая промежуточная сумма и текущий элемент, добавляемый к этой сумме. Предикат вызывается для каждого отдельного элемента и, как ожидается, будет возвращать обновленную сумму.

Если вы хотите суммировать значения в парах, вы можете попробовать что-то вроде этого:

vector<int> vec = {1,4,2,3};
...
int *first = nullptr;
return std::accumulate(vec.begin(), vec.end(), 0,
    [&](int runningSum, int &value) {
        if (first) {
            runningSum += std::min(*first, value);
            first = nullptr;
        } else {
            first = &value;
        }
        return runningSum;
    }
);

Лучшим решением было бы просто изменить ваш vector, чтобы он содержал пару int s (например, std::pair<int, int>) в качестве типа элемента (или, по крайней мере, скопировал ваш вектор int s ввторой vector пар), а затем вы можете накапливать пары как есть:

vector<pair<int,int>> vec = {{1,4},{2,3}};
...
return std::accumulate(vec.begin(), vec.end(), 0,
    [](int runningSum, const pair<int, int> &p) {
        return runningSum + std::min(p.first, p.second);
    }
);
0 голосов
/ 31 октября 2019

Я думаю, что было бы трудно просто использовать накопление сразу для суммирования по мин пары. Возможно, вам придется сначала разделить существующий вектор, а затем преобразовать их в вектор минут, а затем использовать функцию накопления.

Итак, учитывая это, я, возможно, сделал бы это следующим образом:

    std::vector<int> v{ 1,4,2,3};
    std::vector<int> v2;
    std::vector<int> v3;
    std::vector<int> v4;

    std::partition_copy(begin(v),
                        end(v),
                        back_inserter(v2),
                        back_inserter(v3),
                        [toggle = false](int) mutable { return toggle = !toggle; });

    std::transform(begin(v2), end(v2), begin(v3), std::back_inserter(v4), [](auto a, auto b)
    {
        return std::min(a,b);
    });

    auto sum_of_min_in_pairs =  std::accumulate(begin(v4), end(v4), 0);

Обратите внимание, что приведенный выше код будет иметь проблемы, если ваш вектор не имеет четного количества элементов. В противном случае, преобразуйте его в пару, с некоторыми значениями по умолчанию, чтобы соответствовать остатку, в зависимости от того, чего вы хотите достичь.

На веб-сайте STL cppreference.com станет вашим другом. Вокруг есть несколько книг, которые я очень рекомендую.

  • Эффективный STL Скотта Мейерса
  • Стандартная библиотека C ++ Николая Йосуттиса
...