Jak uzyskać bieżący indeks pętli podczas korzystania z Iteratora?


108

Używam Iteratora do iteracji w kolekcji i chcę uzyskać indeks bieżącego elementu.

Jak mogę to zrobić?



1
@finnw Nie sądzę, że są duplikatami. To pytanie dotyczy Iteratora, a drugie używa pętli for-each. Oba pytania rozwiązuje się w podobny sposób, więc odpowiedzi są duplikatami, a nie pytaniem.
Robert

Odpowiedzi:


92

Użyj własnej zmiennej i zwiększ ją w pętli.


6
Ale zobacz też sugestię @ mateusz-Dymczyk dot it.nextIndex(). Przydatne, gdy kolekcja jest listą.
noamtm

113

Miałem to samo pytanie i okazało się, że użycie ListIteratora działa. Podobnie jak w powyższym teście:

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

ListIterator iter = list.listIterator();

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

Upewnij się, że wywołujesz nextIndex ZANIM faktycznie otrzymasz next ().


5
Dziękuję za wspomnienie `` Upewnij się, że zadzwonisz do nextIndex, ZANIM faktycznie otrzymasz next () ''
Gangadhar JANNU

Dzięki, wcześniej o tym nie wiedziałem. Ostrzegam, że ListIterator jest dwukierunkowy, podczas gdy Iterator jest jednokierunkowy. Tak długo, jak unikasz poruszania się tam iz powrotem za pomocą tego, co faktycznie jest kursorem, powinieneś być bezpieczny.
user2910265

28

Oto sposób, aby to zrobić, używając własnej zmiennej i zachowując zwięzłość:

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

Wyjście (zgadłeś):

0: zero
1: one
2: two

Zaletą jest to, że nie zwiększasz indeksu w pętli (chociaż musisz uważać, aby wywoływać Iterator # next tylko raz na pętlę - po prostu zrób to na górze).


3
Jeśli sam utworzysz iterator, możesz również użyć elementu ListIterator i nie potrzebujesz oddzielnej zmiennej int.
Robert Klemme,

1
Jeśli używasz `` statycznego importu '' dla Arrays.asList, możesz po prostu napisaćasList("zero", "one", "two")
karmakaze

dokładnie tak zrobiłem, zanim przeczytałem odpowiedź Paula. Zdecydowanie odradzam Waszą drogę, ponieważ nie widzę w tym żadnej korzyści. Czy uważasz, że jest korzyść (poza wymienioną). Dlaczego nie użyłeś pętli for-each? Jeśli używasz własnej zmiennej, jawne definiowanie Iteratora nie jest konieczne.
Willi Mentzel

@progressive_overload tylko jeśli potrzebujesz Iteratora (jak na pytanie, np. do przekazania do biblioteki), czego przykład nie pokazuje. W tym przykładzie masz zmienną poza pętlą i musisz uważać, aby wywołać raz #next. W przykładzie Paula nie ma zmiennych poza pętlą, ale musisz uważać, aby wywołać #next i #nextIndex razem raz (aw praktyce, jeśli zostaną użyte więcej niż raz, zostaną one wciągnięte do zmiennych lokalnych, czego ten przykład nie robi t pokaż).
Tom Clift

23

Możesz użyć ListIteratordo liczenia:

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

12

Jaki rodzaj kolekcji? Jeśli jest to implementacja interfejsu List, możesz po prostu użyć it.nextIndex() - 1.


4

Użyj ListIterator, aby wykonać iterację w kolekcji. Jeśli kolekcja nie jest listą, należy Arrays.asList(Collection.toArray())najpierw użyć, aby przekształcić ją w listę.


3

po prostu zrób coś takiego:

        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
Wywołanie indexOf () będzie wymagało dodatkowego skanowania listy urządzeń. Szybciej będzie po prostu zwiększyć lokalny licznik.
Greg Brown

1
Zgoda. nie jest to najbardziej wydajne rozwiązanie.
Sunny

1
Wygląda na to, że zaktualizowałeś przykład, aby był bardziej wydajny.
Greg Brown


1

Zobacz tutaj .

iterator.nextIndex()podałby indeks elementu, który zostałby zwrócony przez kolejne wywołanie next().


Iterator interfejsu NIE ma metody nextIndex (). Musisz jawnie użyć do tego ListIteratora, ale OP zapytał konkretnie o Iterator.
Fran Marzoa,

0

Wszystko, czego potrzebujesz, aby użyć iterator.nextIndex (), aby zwrócić bieżący indeks, na którym znajduje się iterator. Może to być trochę łatwiejsze niż użycie własnej zmiennej licznika (która nadal działa).

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

Ten kod przejdzie przez listę list1 po jednym elemencie na raz i wydrukuje tekst elementu, a następnie „jest w indeksie”, a następnie wydrukuje indeks, w którym iterator go znalazł. :)


1
W rzeczywistości twój kod jest wyłączony o jeden, ponieważ próbuje wyświetlić indeks PO wywołaniu go.next ().
Henrik Aasted Sørensen

0

Chociaż masz już odpowiedź, pomyślałem, aby dodać trochę informacji.

Jak wyraźnie wspomniałeś Kolekcje, nie możesz użyć listIteratordo pobrania indeksu dla wszystkich typów kolekcji.

Lista interfejsów - ArrayList, LinkedList, Vector i Stack.

Ma zarówno iterator()ilistIterator()

Ustaw interfejsy - HashSet, LinkedHashSet, TreeSet i EnumSet.

Ma jedynie iterator()

Interfejsy map - HashMap, LinkedHashMap, TreeMap i IdentityHashMap

Nie ma iteratorów, ale można je iterować za pomocą keySet()/ values()lubentrySet() as keySet()oraz entrySet()zwraca Seti values()zwracaCollection .

Dlatego lepiej jest używać iterators()z ciągłym zwiększaniem wartości, aby uzyskać bieżący indeks dla dowolnego typu kolekcji.


-1

To byłoby najprostsze rozwiązanie!

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;

}

Testowane na gcc-9 z -std=c++11 flagą

Wynik:

0
1
2
3
4

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.