Iteratorを使用しているときに現在のループインデックスを取得する方法


107

Iteratorを使用してコレクションを反復処理していますが、現在の要素のインデックスを取得します。

どうやってやるの?



1
@finnw重複しているとは思いません。この質問はIteratorを使用して尋ねています。もう1つはfor-eachループを使用しています。どちらの質問も同様のアプローチで解決されるため、質問ではなく回答が重複しています。
Robert

回答:


92

独自の変数を使用して、ループ内でインクリメントします。


6
ただし、@ mateusz-dymczykに関する提案も参照してくださいit.nextIndex()。コレクションがリストの場合に役立ちます。
noamtm 2016

113

同じ質問があり、ListIteratorを使用して機能していることがわかりました。上記のテストと同様:

List<String> list = Arrays.asList("zero", "one", "two");

ListIterator iter = list.listIterator();

while (iter.hasNext()) {
    System.out.println("index: " + iter.nextIndex() + " value: " + iter.next());
}

next()を実際に取得する前に、必ずnextIndexを呼び出してください。


5
「next()を実際に取得する前に、nextIndexを呼び出すようにしてください」に言及していただきありがとうございます
Gangadhar JANNU

ありがとう、私はこれについて以前に知りませんでした。私が注意するのは、ListIteratorは双方向ですが、Iteratorは単方向であることです。実質的にカーソルであるもので前後に移動しない限り、安全である必要があります。
user2910265

28

独自の変数を使用して簡潔にする方法は次のとおりです。

List<String> list = Arrays.asList("zero", "one", "two");

int i = 0;
for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {
    String s = it.next();
    System.out.println(i + ": " + s);
}

出力(予想通り):

0: zero
1: one
2: two

利点は、ループ内でインデックスをインクリメントしないことです(ただし、ループごとに1回だけIterator#nextを呼び出すように注意する必要があります-上部で実行してください)。


3
イテレータを自分で作成する場合は、ListIteratorも使用でき、個別のint変数は必要ありません。
Robert Klemme、2012

1
Arrays.asListに「静的インポート」を使用する場合は、次のように記述できますasList("zero", "one", "two")
karmakaze

それが、ポールの答えを読む前のやり方でした。私はあなたのやり方を強く思いません。私にはそれに対する利点が何もないからです。利点があると思いますか(言及されたものを除いて)。for-eachループを使用しなかったのはなぜですか?独自の変数を使用する場合、イテレータを明示的に定義する必要はありません。
Willi Mentzel、2016年

@progressive_overloadは、(例のように、ライブラリーに渡すために)イテレーターが必要な場合にのみ使用できますが、例には示されていません。この例では、ループの外側に変数があり、#nextを1回呼び出すように注意する必要があります。Paulの例では、ループの外側に変数はありませんが、#nextと#nextIndexを一緒に1回呼び出すように注意する必要があります(実際には、2回以上使用すると、それらはローカル変数にプルされます。 tショー)。
トムクリフト2016年

23

ListIteratorカウントに使用できます。

final List<String> list = Arrays.asList("zero", "one", "two", "three");

for (final ListIterator<String> it = list.listIterator(); it.hasNext();) {
    final String s = it.next();
    System.out.println(it.previousIndex() + ": " + s);
}


4

ListIteratorを使用して、コレクションを反復処理します。コレクションがリストでない場合は、Arrays.asList(Collection.toArray())最初にリストに変換するために使用します。


3

次のようなことをしてください:

        ListIterator<String> it = list1.listIterator();
        int index = -1;
        while (it.hasNext()) {
            index++;
            String value = it.next();
            //At this point the index can be checked for the current element.

        }

4
indexOf()を呼び出すと、デバイスリストの追加のスキャンが必要になります。ローカルカウンタをインクリメントする方が速くなります。
グレッグブラウン

1
同意した。これは最も効率的なソリューションではありません。
サニー

1
より効率的になるように例を更新したようです。
グレッグブラウン


1

こちらをご覧ください

iterator.nextIndex()の後続の呼び出しで返される要素のインデックスを提供しますnext()


インターフェースIteratorにはnextIndex()メソッドがありません。そのためには明示的にListIteratorを使用する必要がありますが、OPはIteratorについて特に質問しました。
フランマルゾア2018

0

iterator.nextIndex()を使用して、イテレータが存在する現在のインデックスを返すために必要なすべてのこと。これは、独自のカウンター変数を使用するよりも少し簡単かもしれません(まだ機能します)。

public static void main(String[] args) {    
    String[] str1 = {"list item 1", "list item 2", "list item 3", "list item 4"};
    List<String> list1 = new ArrayList<String>(Arrays.asList(str1));

    ListIterator<String> it = list1.listIterator();

    int x = 0;

    //The iterator.nextIndex() will return the index for you.
    while(it.hasNext()){
        int i = it.nextIndex();
        System.out.println(it.next() + " is at index" + i); 
    }
}

このコードは、list1リストを一度に1項目ずつ調べ、項目のテキストを出力し、次に「is at index」で、イテレータが見つけたインデックスを出力します。:)


1
実際、コードはit.next()を呼び出した後にインデックスを表示しようとするため、コードは1つずれています。
Henrik AastedSørensen2014

0

あなたはすでに答えを持っていますが、いくつかの情報を追加しようと考えました。

コレクションを明示的に述べたように、listIteratorすべてのタイプのコレクションのインデックスを取得するために使用することはできません。

リストインターフェイス -ArrayList、LinkedList、Vector、Stack。

両方iterator()ありますlistIterator()

インターフェースの設定 -HashSet、LinkedHashSet、TreeSet、EnumSet。

のみ iterator()

マップインターフェイス -HashMap、LinkedHashMap、TreeMapおよびIdentityHashMap

反復子はありませんが、keySet()/ values()またはentrySet()as を使用して反復でき、return keySet()およびentrySet()returns Setvalues()返しますCollection

したがって、iterators()任意のコレクション型の現在のインデックスを取得するには、値を連続的にインクリメントして使用する方が適切です。


-1

これが最も簡単な解決策です。

std::vector<double> v (5);

for(auto itr = v.begin();itr != v.end();++itr){

 auto current_loop_index = itr - v.begin();

  std::cout << current_loop_index << std::endl;

}

-std=c++11フラグ付きのgcc-9でテスト済み

出力:

0
1
2
3
4

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.