web-dev-qa-db-ger.com

Wie lassen sich Elemente eines C++ - Vektors zusammenfassen?

Was sind die guten Wege, um die Summe aller Elemente in einem std::vector zu finden?

Angenommen, ich habe einen Vektor std::vector<int> vector mit einigen Elementen. Nun möchte ich die Summe aller Elemente ermitteln. Was sind die verschiedenen Möglichkeiten für dasselbe?

189
Prasoon Saurav

Eigentlich gibt es einige Methoden.

int sum_of_elems = 0;

C++ 03

  1. Classic für Schleife:

    for(std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it)
        sum_of_elems += *it;
    
  2. Verwendung eines Standardalgorithmus: 

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

    flagge

    Seien Sie vorsichtig mit dem Akkumulieren. Der Typ des letzten Arguments wird nicht nur für den Anfangswert verwendet, sondern auch für den Typ des Ergebnisses. Wenn Sie dort ein int setzen, wird es ints angesammelt, auch wenn der Vektor float ist. Wenn Sie Gleitkommazahlen summieren, ändern Sie 0 in 0.0 oder 0.0f (dank nneonneo).

C++ 11 und höher

  1. std::for_each verwenden:

    std::for_each(vector.begin(), vector.end(), [&] (int n) {
        sum_of_elems += n;
    });
    
  2. Verwenden einer bereichsbasierten for-Schleife (Dank an Roger Pate):

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

Prasoon hat bereits einen Host mit verschiedenen (und guten) Wegen dafür angeboten, die hier nicht wiederholt werden müssen. Ich möchte jedoch einen alternativen Ansatz für die Geschwindigkeit vorschlagen.

Wenn Sie dies einiges tun, sollten Sie in Betracht ziehen, Ihren Vektor so zu "unterteilen", dass die Summe der Elemente separat verwaltet wird (nicht eigentlich -) das Fehlen eines virtuellen Destruktors - ich spreche eher von einer Klasse, die die Summe und einen Vektor enthält (has-a und nicht is-a) und die vektorähnlichen Methoden bereitstellt.

Für einen leeren Vektor wird die Summe auf Null gesetzt. Fügen Sie bei jeder Einfügung in den Vektor das Element der Summe hinzu. Bei jedem Löschvorgang subtrahieren. Grundsätzlich wird alles das den zugrundeliegenden Vektor ändern kann, abgefangen, um sicherzustellen, dass die Summe konsistent bleibt.

Auf diese Weise haben Sie eine sehr effiziente O(1) - Methode zum "Berechnen" der Summe zu einem beliebigen Zeitpunkt (geben Sie einfach die aktuell berechnete Summe zurück). Das Einfügen und Löschen wird etwas länger dauern, wenn Sie die Gesamtsumme anpassen, und Sie sollten diesen Leistungstreffer berücksichtigen.

Vektoren, bei denen die Summe öfter benötigt wird, als der Vektor geändert wird, profitieren wahrscheinlich von diesem Schema, da sich die Kosten für die Berechnung der Summe über alle Zugriffe amortisieren. Wenn Sie die Summe nur jede Stunde benötigen und sich der Vektor dreitausend Mal pro Sekunde ändert, ist er offensichtlich nicht geeignet.

So etwas würde genügen:

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

Natürlich ist das Pseudo-Code, und Sie möchten vielleicht ein wenig mehr Funktionalität haben, aber es zeigt das grundlegende Konzept.

30
paxdiablo

Warum die Summation vorwärts durchführen, wenn Sie rückwärts machen können? Gegeben:

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

Wir können Subskription verwenden, rückwärts zählen:

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

Wir können bereichsgeprüfte "Subskriptionen" verwenden, die rückwärts zählen (nur für den Fall):

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

Wir können Reverse-Iteratoren in einer for-Schleife verwenden:

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

Wir können Forward-Iteratoren verwenden, die rückwärts in einer For-Schleife (oooh, tricky!) Iterieren:

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

Wir können accumulate mit Reverse-Iteratoren verwenden:

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

Wir können for_each mit einem Lambda-Ausdruck unter Verwendung von Reverse-Iteratoren verwenden:

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

Wie Sie sehen können, gibt es also genauso viele Möglichkeiten, den Vektor rückwärts zu summieren, als den Vektor vorwärts zu summieren, und einige davon sind viel aufregender und bieten weitaus mehr Möglichkeiten für Fehler, die sich nicht lösen.

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

Am einfachsten ist es, std:accumuate eines vector<int> A zu verwenden:

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

Ich bin ein Perl-Benutzer. Ein Spiel, das wir haben, besteht darin, alle Möglichkeiten zu finden, eine Variable zu erhöhen. Die Antwort auf wie viele Arten, um die Summe der Elemente eines Vektors in C++ zu ermitteln, ist wahrscheinlich an infinity...

Meine 2 Cent:

Verwenden Sie BOOST_FOREACH, um sich von der hässlichen Iteratorsyntax zu befreien:

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

durchlaufen der Indizes (sehr einfach zu lesen).

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

Dieses andere ist destruktiv und greift wie ein Stapel auf den Vektor zu:

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

Nur C++ 0x:

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

Dies ist dem BOOST_FOREACH ähnlich, das an anderer Stelle erwähnt wurde, und hat in komplexeren Situationen den gleichen Vorteil der Klarheit, verglichen mit Stateful-Funktoren, die mit "akkumulieren" oder "for_each" verwendet werden.

5
Roger Pate

Man kann std :: valarray auch so verwenden

#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;
}

Einige finden diesen Weg möglicherweise nicht effizient, da die Größe des Valarrays so groß wie der Vektor sein muss, und das Initialisieren des Valarrays wird ebenfalls Zeit erfordern.

Verwenden Sie es in diesem Fall nicht und verwenden Sie es als eine andere Art, die Sequenz zusammenzufassen.

Vielen Dank 

2
NeutronStar

Am einfachsten finde ich die Summe aller Elemente eines Vektor

#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;

}

In diesem Programm habe ich einen Vektor der Größe 10 und bin mit 1 initialisiert. Ich habe die Summe durch eine einfache Schleife wie im Array berechnet.

0