web-dev-qa-db-fra.com

Comment résumer les éléments d'un vecteur C++?

Quels sont les bons moyens de trouver la somme de tous les éléments dans un std::vector?

Supposons que j'ai un vecteur std::vector<int> vector avec quelques éléments. Maintenant, je veux trouver la somme de tous les éléments. Quelles sont les différentes manières pour le même?

189
Prasoon Saurav

En fait, il existe plusieurs méthodes.

int sum_of_elems = 0;

C++ 03

  1. Classique pour la boucle:

    for(std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it)
        sum_of_elems += *it;
    
  2. En utilisant un algorithme standard: 

    #include <numeric>
    
    sum_of_elems = std::accumulate(vector.begin(), vector.end(), 0);
    

    drapeau

    Faites attention avec accumuler. Le dernier type d'argument est utilisé non seulement pour la valeur initiale, mais également pour le type du résultat. Si vous mettez un int ici, il accumulera des ints même si le vecteur a float. Si vous additionnez des nombres à virgule flottante, remplacez 0 par 0.0 ou 0.0f (grâce à nneonneo).

C++ 11 et supérieur

  1. Utiliser std::for_each:

    std::for_each(vector.begin(), vector.end(), [&] (int n) {
        sum_of_elems += n;
    });
    
  2. Utiliser une boucle for basée sur la plage (grâce à Roger Pate):

    for (auto& n : vector)
        sum_of_elems += n;
    
360
Prasoon Saurav

Prasoon a déjà proposé une foule de façons (et de bonnes) de faire cela, dont aucune n'a besoin d'être répétée ici. Je voudrais suggérer une approche alternative pour la vitesse cependant.

Si vous envisagez de faire cela assez souvent, vous pouvez envisager de "sous-classer" votre vecteur afin qu'une somme d'éléments soit maintenue séparément (et non en fait vecteur de sous-classement qui est incertain en raison de l'absence d'un destructeur virtuel - je parle plus d'une classe qui contient la somme et un vecteur, has-a plutôt que is-a, et fournit les méthodes de type vecteur).

Pour un vecteur vide, la somme est définie sur zéro. A chaque insertion dans le vecteur, ajoutez l'élément en cours d'insertion à la somme. À chaque suppression, soustrayez-le. Fondamentalement, n'importe quoi qui peut changer le vecteur sous-jacent est intercepté pour assurer la cohérence de la somme.

De cette façon, vous disposez d'une méthode très efficace O(1) pour "calculer" la somme à tout moment (il suffit de renvoyer la somme calculée). L'insertion et la suppression prendront un peu plus longtemps au fur et à mesure que vous ajustez le total et vous devez prendre en compte cet impact sur les performances.

Les vecteurs dont la somme est nécessaire plus souvent que le vecteur n'est modifié sont ceux susceptibles de bénéficier de ce schéma, car le coût de calcul de la somme est amorti sur tous les accès. Évidemment, si vous n'avez besoin que de la somme toutes les heures et que le vecteur change trois mille fois par seconde, cela ne conviendra pas.

Quelque chose comme cela suffirait:

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

Évidemment, c'est du pseudo-code et vous voudrez peut-être un peu plus de fonctionnalités, mais cela montre le concept de base.

30
paxdiablo

Pourquoi effectuer la somme en avant quand vous pouvez le faire en arrière ? Donné:

std::vector<int> v;     // vector to be summed
int sum_of_elements(0); // result of the summation

Nous pouvons utiliser un indice, compter à rebours:

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v[i-1];

Nous pouvons utiliser un "indice" à plage contrôlée, comptant à rebours (au cas où):

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v.at(i-1);

Nous pouvons utiliser des itérateurs inversés dans une boucle for:

for(std::vector<int>::const_reverse_iterator i(v.rbegin()); i != v.rend(); ++i)
    sum_of_elements += *i;

Nous pouvons utiliser des itérateurs en avant, itérant en arrière, dans une boucle for (oooh, un peu compliqué!):

for(std::vector<int>::const_iterator i(v.end()); i != v.begin(); --i)
    sum_of_elements += *(i - 1);

Nous pouvons utiliser accumulate avec les itérateurs inversés:

sum_of_elems = std::accumulate(v.rbegin(), v.rend(), 0);

Nous pouvons utiliser for_each avec une expression lambda en utilisant des itérateurs inversés:

std::for_each(v.rbegin(), v.rend(), [&](int n) { sum_of_elements += n; });

Ainsi, comme vous pouvez le constater, il existe autant de façons de résumer le vecteur en arrière que de le faire, et certaines d’entre elles sont beaucoup plus excitantes et offrent une possibilité bien plus grande d’erreurs erronées.

22
James McNellis
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);
14
rafak

Le moyen le plus simple consiste à utiliser std:accumuate d'un vector<int> A:

#include <numeric>
cout << accumulate(A.begin(), A.end(), 0);
7
beahacker

Je suis un utilisateur de Perl. Notre jeu consiste à trouver toutes les façons d’incrémenter une variable. La réponse à combien de façons de trouver la somme des éléments d'un vecteur en C++ est probablement an infinity...

Mes 2 centimes:

En utilisant BOOST_FOREACH, pour vous libérer de la syntaxe laide de l'itérateur:

sum = 0;
BOOST_FOREACH(int & x, myvector){
  sum += x;
}

itération sur des index (très facile à lire).

int i, sum = 0;
for (i=0; i<myvector.size(); i++){
  sum += myvector[i];
}

Cet autre est destructif, accédant au vecteur comme une pile:

while (!myvector.empty()){
   sum+=myvector.back();
   myvector.pop_back();
}
5
kriss

C++ 0x uniquement:

vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;

Ceci est similaire au BOOST_FOREACH mentionné ailleurs et a le même avantage de clarté dans des situations plus complexes, par rapport aux foncteurs à états utilisés avec accumulate ou for_each.

5
Roger Pate

On peut aussi utiliser std :: valarray comme ceci

#include<iostream>
#include<vector>
#include<valarray>

int main()
{
std::vector<int> seq{1,2,3,4,5,6,7,8,9,10};
std::valarray<int> seq_add {seq.data(), seq.size()};
std::cout << "sum = " << seq_add.sum() << "\n";

return 0;
}

Certains trouveront peut-être que cette méthode n'est pas efficace car la taille de valarray doit être égale à celle du vecteur et l'initialisation de valarray prendra également du temps.

Dans ce cas, ne l'utilisez pas et considérez-le comme un autre moyen de résumer la séquence.

Merci 

2
NeutronStar

J'ai trouvé le moyen le plus facile de trouver la somme de tous les éléments d'un vecteur

#include <iostream>
#include<vector>
using namespace std;

int main()
{
    vector<int>v(10,1);
    int sum=0;
    for(int i=0;i<v.size();i++)
    {
        sum+=v[i];
    }
    cout<<sum<<endl;

}

Dans ce programme, j'ai un vecteur de taille 10 et je suis initialisé par 1. J'ai calculé la somme par une simple boucle comme dans un tableau.

0
Ravi Kumar Yadav