Каковы хорошие способы найти сумму всех элементов в a std::vector
?
Предположим, что у меня есть вектор std::vector<int> vector
с несколькими элементами в нем. Теперь я хочу найти сумму всех элементов. Каковы различные пути к тому же?
На самом деле существует довольно много методов.
int sum_of_elems = 0;
Классический цикл for:
for(std::vector::iterator it = vector.begin(); it != vector.end(); ++it)
sum_of_elems += *it;
Использование стандартного алгоритма:
#include
sum_of_elems = std::accumulate(vector.begin(), vector.end(), 0);
flag
Будьте осторожны с accumulate. Тип последнего аргумента используется не только для начального значения, но и для типа результата. Если вы поместите туда int, он будет накапливать ints, даже если вектор имеет float. Если вы суммируете числа с плавающей точкой, измените 0
на 0.0
или 0.0f
(спасибо nneonneo).
Использование std::for_each
:
std::for_each(vector.begin(), vector.end(), [&] (int n) {
sum_of_elems += n;
});
Использование цикла for на основе диапазона (спасибо Роджеру Пейту):
for (auto& n : vector)
sum_of_elems += n;
Prasoon уже предложил множество различных (и хороших) способов сделать это, ни один из которых не нуждается в повторении здесь. Однако я хотел бы предложить альтернативный подход к скорости.
Если вы собираетесь делать это совсем немного, вы можете рассмотреть возможность «подкласса» вашего вектора, чтобы сумма элементов поддерживалась отдельно (а не на самом деле вектор подкласса что сомнительно из-за отсутствия виртуального деструктора - я говорю больше о классе, который содержит сумму и вектор внутри него, has-a
, а не is-a
, и предоставляет векторные методы).
Для пустого вектора сумма обнуляется. При каждой вставке в вектор добавляйте вставляемый элемент к сумме. При каждом удалении вычитайте это. По сути, все , что может изменить лежащий в основе вектор, перехватывается, чтобы гарантировать согласованность суммы.
Таким образом, у вас будет очень эффективный метод O (1) для «вычисления» суммы в любой момент времени (просто верните текущую вычисленную сумму). Вставка и удаление займут немного больше времени, поскольку вы скорректируете общее количество, и вы должны принять во внимание это снижение производительности.
Векторы, сумма которых требуется чаще, чем изменение вектора, вероятно, выиграют от этой схемы, поскольку затраты на вычисление суммы амортизируются по всем доступам. Очевидно, что если вам нужна только сумма каждый час, а вектор меняется три тысячи раз в секунду, это не подойдет.
Что-то вроде этого было бы достаточно:
class UberVector:
private Vector<int> vec
private int sum
public UberVector():
vec = new Vector<int>()
sum = 0
public getSum():
return sum
public add (int val):
rc = vec.add (val)
if rc == OK:
sum = sum + val
return rc
public delindex (int idx):
val = 0
if idx >= 0 and idx < vec.size:
val = vec[idx]
rc = vec.delindex (idx)
if rc == OK:
sum = sum - val
return rc
Очевидно, что это псевдокод, и вы можете захотеть иметь немного больше функциональных возможностей, но он показывает основную концепцию.
Я пользователь Perl, и у нас есть игра - найти всевозможные способы увеличить переменную... здесь нет ничего особенного. Ответ на вопрос, сколько способов найти сумму элементов вектора в C++, вероятно, бесконечность
...
Мои 2 цента:
использование BOOST_FOREACH, чтобы избавиться от уродливого синтаксиса итератора:
sum = 0;
BOOST_FOREACH(int & x, myvector){
sum += x;
}
итерация по индексам (действительно легко читается).
int i, sum = 0;
for (i=0; i<myvector.size(); i++){
sum += myvector[i];
}
Этот другой - деструктивный, доступ к вектору как к стеку:
while (!myvector.empty()){
sum+=myvector.back();
myvector.pop_back();
}
Зачем выполнять суммирование в прямом направлении, если это можно сделать в обратном направлении ? Дано:
std::vector<int> v; // vector to be summed
int sum_of_elements(0); // result of the summation
Мы можем использовать индексирование в обратном направлении:
for (int i(v.size()); i > 0; --i)
sum_of_elements += v[i-1];
Мы можем использовать «индексирование в обратном направлении» с проверкой диапазона, считая в обратном порядке (на всякий случай):
for (int i(v.size()); i > 0; --i)
sum_of_elements += v.at(i-1);
Мы можем использовать обратные итераторы в цикле for:
for(std::vector<int>::const_reverse_iterator i(v.rbegin()); i != v.rend(); ++i)
sum_of_elements += *i;
Мы можем использовать прямые итераторы, выполняя итерацию назад, в цикле for (ооо, сложно!):
for(std::vector<int>::const_iterator i(v.end()); i != v.begin(); --i)
sum_of_elements += *(i - 1);
Мы можем использовать Накопить
с обратными итераторами:
sum_of_elems = std::accumulate(v.rbegin(), v.rend(), 0);
Мы можем использовать for_each
с лямбда-выражением с использованием обратных итераторов:
std::for_each(v.rbegin(), v.rend(), [&](int n) { sum_of_elements += n; });
Итак, как вы можете видеть, существует столько же способов суммирования вектора в обратном направлении, сколько способов суммирования вектора вперед, и некоторые из них гораздо более интересны и предлагают гораздо больше возможность для единичных ошибок.
Только C ++ 0x:
vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;
Это похоже на BOOST_FOREACH, упомянутое в другом месте, и дает такое же преимущество ясности в более сложных ситуациях по сравнению с функторами с отслеживанием состояния, используемыми с accumulate или for_each.
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);