2012-09-19 16 views
13

私は、ベクトルの各要素にアクセスしても要素がであるもののインデックスを知る必要があります。ベクターを反復処理する方法と、要素のインデックスも知る方法はありますか?

これまでのところ、私は二つの方法型シグネチャを残す

for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index) 

を思い付くことができます。私は1つは、より効率的であるか、これを行うには良い方法があるオート

for (int index = 0; index < aVector.size(); ++index) 
{ 
    // access using [] 
} 

を使用することはできませんようにも見えますか?

+1

本質的ないくつかの根本的な理由からインデックスが必要な場合は、2番目のバージョンを使用してください。 –

+2

C++ y uには 'enumerate'がありません – Fanael

+0

はい、インデックスが必要な場合は後者を選んでください。 –

答えて

12

は、それは少し違いになります。おそらく読むのが簡単だから2番目を選ぶだろうし、更新するループ変数が1つしかないのでおそらくほんの少し速いだろう。別の方法としては、次のとおりです。非ランダム・アクセス・コンテナ用

for (auto it = aVector.begin(); it != aVector.end(); ++it) { 
    int index = std::distance(aVector.begin(), it); 
} 

[]が利用できない、とstd::distanceは非効率的です。その場合、インデックスが必要な場合は、最初の方法が良いでしょう(ただし、for-initialiserで2つの異なる型付き変数を宣言しようとしないように修正する必要があります)。

+0

これは私の言うことです:p – matiu

+0

これは、 'std :: distance'が' std :: iterator_traits :: difference_type'を返すという事実を反映するように修正する必要があります。これは 'int '。 ( 'int'をオーバーフローさせるのに十分な大きさのコンテナを持つ人はほとんどいないという事実は言い訳ではありません。)' auto'を使うもう一つの理由は、 'it'のためにしたのは変ですが、' index'ではありません。 –

6

答えは質問にあります。"要素のインデックスを知っていますか?"

ので -

for (int index = 0; index < aVector.size(); ++index) 
{ 
    // access using [] 
} 

パフォーマンスワイズそれらは同じだ(しかし、あなたは常に自分自身をプロファイルすることができます)。

+1

indexは 'int'の代わりに' size_t'でなければなりません –

+3

@Rémipedantically、ベクトル :: size_type :) –

0
for (iterator it = aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index) 

これはコンパイルされません。しかし、それは本当に重要ではありません。なぜなら、我々がstd::vectorについて話している限り、インデックスでアクセスするのは簡単なポインタの算術と逆参照ですから、実際はイテレータと同じくらい速いです。あなたのバージョン2はOKです。

(あなたが速さについては本当に心配している場合)、私はしかし、さらに最適化します:ベクターまたは他のランダムアクセスコンテナの

for (int index = 0, size = aVector.size(); index < size; ++index) 
{ 
    // access using [] 
} 
+0

なぜ最初のコンパイルはありませんか?あなたは正しいイテレータの型を入れましたか? – unj2

+0

@ kunj2aan:無関係な型の変数( 'iterator'と' int')を単一の宣言で宣言することはできません。 –

+0

@ kunj2aanなぜあなたは[試してみてください](http://ideone.com/DF6TG)ですか?ソリューションはシンプルです(http://ideone.com/yw5Lw)。 – Fiktik

0

C++ 11:

for (auto i=aVector.begin(); i!=aVector.end(); ++i) { 
    cout << "I am at position: " << i-aVector.begin() << endl; 
    cout << "contents here is: " << *i << endl; 
} 

C++の古い学校:ここ

for (vector<int>::const_iterator i=aVector.begin(); i!=aVector.end(); ++i) { 
    cout << "I am at position: " << i-aVector.begin() << endl; 
    cout << "contents here is: " << *i << endl; 
} 
+2

最初のものでは、 'i'はベクトルの要素であり、インデックスやイテレータではありません。 range-style forループからインデックスを取得することはできません。 (ベクトルの場合、 '&i-&vector [0]'でハックすることができますが、コンテナのタイプが変更された場合、それは黙ってひどく壊れてしまいます。 –

+0

@MikeSeymourあなたが正しいです、私はあまりにも急いでいました。良いコメント:) – matiu

+0

@MikeSeymour forループが 'for(auto&i:aVector)'を使用していた場合、あなたのハックはうまくいくと思うでしょうか?そうでなければ、今書いているように 'i'はベクトルの要素。 –

3

Boost.Iterator libraryからzip_iteratorcounting_iteratorを使用したソリューションです。おそらくwayあなたのユースケースではオーバーキルですが、ベクトルだけでなくあらゆる範囲で作業し、iteratorベースの標準アルゴリズムの設計にうまく収まるという利点があります。

#include <boost/iterator/counting_iterator.hpp> 
#include <boost/iterator/zip_iterator.hpp> 

#include <algorithm> 
#include <iostream> 
#include <list> 

int main() 
{ 
    typedef std::list<int> container; 

    typedef boost::tuple< 
     container::iterator, 
     boost::counting_iterator<container::size_type> 
    > tuple_type; 

    typedef boost::zip_iterator<tuple_type> it_type; 

    container l{1, 2, 3, 4}; 

    it_type begin(tuple_type(l.begin(), 0)); 
    it_type const end(tuple_type(l.end(), l.size())); 

    // sample use with for loop 
    for (it_type it = begin; it != end ; ++it) 
    { 
     int value = it->get<0>(); 
     int index = it->get<1>(); 
     // do whatever you want with value and index 
    } 

    // sample use with standard algorithm 
    auto res = std::find_if(begin, end, 
     [](boost::tuple<int, int> const & t) 
     { return t.get<0>() > 2; }); // find first element greater than 2 

    std::cout << "Value: " << res->get<0>() << '\n' << 
       "Index: " << res->get<1>() << '\n'; 
} 
1

ブーストの範囲indexedアダプタを使用すると、範囲のイテレータを現在のインデックス(duh)を返すindexメソッドで拡張できます。

悲しいこと
#include <boost/range/adaptor/indexed.hpp> 

// ... 
auto&& r = vec | boost::adaptors::indexed(0); 
for(auto it(begin(r)), ite(end(r)); it != ite; ++it) 
    std::cout << it.index() << ": " << *it << "\n"; 

indexはイテレータのメソッド一部であることから、これはあなたが唯一の要素へのアクセスを与えている、ループあるいはBOOST_FOREACHのための新しい範囲ベースを使用することはできません。疑わしい値の定型的な回避策を次に示します。

関連する問題