web-dev-qa-db-ja.com

C ++ベクトルの要素をまとめるにはどうすればいいですか?

std::vectorのすべての要素の合計を見つけるための良い方法は何ですか?

いくつかの要素を含むベクトルstd::vector<int> vectorがあるとします。今、私はすべての要素の合計を見つけたいと思います。同じためのさまざまな方法は何ですか?

199
Prasoon Saurav

実際にはかなりの数の方法があります。

int sum_of_elems = 0;

C++ 03

  1. ループのための古典:

    for(std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it)
        sum_of_elems += *it;
    
  2. 標準的なアルゴリズムを使う:

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

    累積には注意してください。最後の引数の型は初期値だけでなく結果の型にも使用されます。あなたがそこにintを入れると、たとえベクトルがfloatを持っていてもそれはintを蓄積するでしょう。浮動小数点数を合計する場合は、00.0または0.0fに変更してください(nneonneoのおかげで)。

C++ 11以上

  1. std::for_eachを使う:

    std::for_each(vector.begin(), vector.end(), [&] (int n) {
        sum_of_elems += n;
    });
    
  2. 範囲ベースのforループを使用する(Roger Pateに感謝)

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

Prasoonはすでにこれを行うためのさまざまな(そして良い)方法を多数提供していますが、そのどれもここで繰り返す必要はありません。私はスピードのための代替アプローチを提案したいのですが。

かなりこれをやろうとしているのであれば、要素の合計が別々に維持されるように実際にはsubとなるように、ベクトルを "サブクラス化"することを検討するとよいでしょう。仮想デストラクタがないため、クラス化されたベクトル - これは、has-aではなくis-aを含み、ベクトルのようなメソッドを提供するクラスのことです。

空のベクトルの場合、合計はゼロに設定されます。ベクトルに挿入するたびに、挿入される要素を合計に追加します。削除するたびに、それを引きます。基本的に、基になるベクトルを変更する可能性があるものは、合計の一貫性を保つためにインターセプトされます。

このように、任意の時点で合計を「計算する」ための非常に効率的なO(1)メソッドがあります(単に現在計算されている合計を返すだけです)。合計を調整すると、挿入と削除に少し時間がかかります。このパフォーマンスへの影響を考慮に入れる必要があります。

ベクトルが変更されるよりも合計がより頻繁に必要とされるベクトルは、合計を計算するコストがすべてのアクセスにわたって償却されるので、この方式から恩恵を受ける可能性が高いものです。明らかに、毎時合計だけが必要で、ベクトルが毎秒3000回変化している場合、それは適切ではありません。

このようなもので十分です。

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

明らかに、それは疑似コードであり、もう少し機能が欲しいかもしれませんが、それは基本的な概念を示しています。

30
paxdiablo

あなたがそれをすることができるとき、なぜ総計を前方に実行します後方に?与えられた:

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ループでは、順方向の反復子を使用して逆方向に反復することができます(oooh、トリッキーです)。

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

accumulateを逆反復子と一緒に使うことができます。

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

そのため、ご覧のとおり、ベクトルを前方に合計するのと同じくらい後方にベクトルを合計する方法があります。これらのいくつかははるかにエキサイティングで、1つずつエラーが発生する可能性がはるかに高くなります。

23
James McNellis

最も簡単な方法はstd:accumuatevector<int> Aを使うことです。

#include <numeric>
cout << accumulate(A.begin(), A.end(), 0);
16
beahacker
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);
14
rafak

私はPerlユーザーです。私たちが持っているゲームは、変数をインクリメントするためのあらゆる方法を見つけることです。 C++でベクトルの要素の合計を見つけるためのいくつの方法に対する答えはおそらくan infinity...です。

私の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];
}

これは破壊的で、スタックのようにvectorにアクセスします。

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

C++ 0xのみ:

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

これは他の場所で言及されているBOOST_FOREACHに類似しており、accumulateまたはfor_eachと共に使用されるステートフルファンクタと比較して、より複雑な状況で明快さという同じ利点を持ちます。

5
Roger Pate

このようにstd :: valarrayを使うこともできます。

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

Valarrayのサイズはvectorのサイズと同じくらい大きくする必要があり、valarrayの初期化にも時間がかかるため、この方法が効率的ではないと考える人もいます。

その場合は、それを使用せずに、シーケンスをまとめるさらに別の方法として使用してください。

ありがとう

2
NeutronStar

ベクトルのすべての要素の合計を見つける最も簡単な方法を見つけました

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

}

このプログラムでは、サイズ10のベクトルがあり、1で初期化されています。配列のような単純なループで合計を計算しました。

0