Come ottenere l'indice del ciclo corrente quando si utilizza Iterator?


107

Sto usando un iteratore per iterare in una raccolta e voglio ottenere l'indice dell'elemento corrente.

Come lo posso fare?



1
@finnw non credo che siano duplicati. Questa domanda sta facendo usando Iterator, l'altro sta usando for-each loop. Entrambe le domande vengono risolte con un approccio simile, quindi le risposte sono duplicate, non la domanda.
Robert

Risposte:


92

Usa la tua variabile e incrementala nel ciclo.


6
Ma vedi anche il suggerimento di @ mateusz-dymczyk su it.nextIndex(). Utile quando la raccolta è una lista.
noamtm

113

Ho avuto la stessa domanda e ho scoperto che l'utilizzo di un ListIterator ha funzionato. Simile al test sopra:

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

ListIterator iter = list.listIterator();

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

Assicurati di chiamare nextIndex PRIMA di ottenere effettivamente next ().


5
Grazie per aver menzionato "Assicurati di chiamare il prossimoIndex PRIMA di ricevere effettivamente il prossimo ()"
Gangadhar JANNU

Grazie, non lo sapevo prima. L'avvertenza che vorrei fare è che ListIterator è bidirezionale mentre Iterator è unidirezionale. Finché eviti di muoverti avanti e indietro con ciò che è effettivamente un cursore, dovresti essere al sicuro.
user2910265

28

Ecco un modo per farlo usando la tua variabile e mantenendola concisa:

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

Uscita (hai indovinato):

0: zero
1: one
2: two

Il vantaggio è che non aumenti il ​​tuo indice all'interno del ciclo (anche se devi stare attento a chiamare Iterator # next una sola volta per ciclo - fallo semplicemente in alto).


3
Se crei tu stesso l'iteratore, puoi usare anche un ListIterator e non hai bisogno della variabile int separata.
Robert Klemme

1
Se utilizzi un '"importazione statica" per Arrays.asList, puoi semplicemente scrivereasList("zero", "one", "two")
karmakaze

questo è esattamente il modo in cui l'ho fatto prima di leggere la risposta di Paul. Scoraggerei vivamente la tua strada, perché non ne vedo alcun vantaggio. Pensa che ci sia un vantaggio (tranne quello menzionato). Perché non hai usato un ciclo for-each? Definire l'iteratore in modo esplicito non è necessario, se si utilizza la propria variabile.
Willi Mentzel

@progressive_overload solo se hai bisogno di un iteratore (come da domanda, ad esempio per passare alla libreria), che l'esempio non mostra. In questo esempio hai una variabile fuori dal ciclo e devi fare attenzione a chiamare #next una volta. Nell'esempio di Paul non ci sono variabili al di fuori del ciclo, ma devi stare attento a chiamare #next e #nextIndex insieme una volta (e in pratica, se usati più di una volta, verrebbero inseriti in variabili locali, cosa che non fa quell'esempio ' t mostra).
Tom Clift

23

Puoi usare ListIteratorper fare il conteggio:

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

Che tipo di raccolta? Se è un'implementazione dell'interfaccia List, puoi semplicemente usare it.nextIndex() - 1.


4

Usa un ListIterator per scorrere la raccolta. Se la raccolta non è una lista per iniziare, usa prima Arrays.asList(Collection.toArray())di trasformarla in una lista.


3

basta fare qualcosa del genere:

        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
La chiamata a indexOf () richiederà un'ulteriore scansione dell'elenco dei dispositivi. Sarà più veloce incrementare semplicemente un contatore locale.
Greg Brown

1
concordato. questa non è la soluzione più efficiente.
Sunny

1
Sembra che tu abbia aggiornato l'esempio per essere più efficiente.
Greg Brown


1

Vedi qui .

iterator.nextIndex()fornirebbe l'indice dell'elemento che sarebbe restituito dalla successiva chiamata a next().


L'interfaccia Iterator NON ha il metodo nextIndex (). È necessario utilizzare esplicitamente un ListIterator per questo, ma l'OP ha interrogato specificamente su Iterator.
Fran Marzoa

0

Tutto ciò che serve per usarlo è iterator.nextIndex () per restituire l'indice corrente su cui si trova l'iteratore. Questo potrebbe essere un po 'più semplice che usare la tua variabile contatore (che funziona ancora).

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

Questo codice scorrerà l'elenco list1 un elemento alla volta e stamperà il testo dell'elemento, quindi "is at index" quindi stamperà l'indice in cui l'iteratore lo ha trovato. :)


1
In realtà, il tuo codice è disattivato di uno perché tenta di visualizzare l'indice DOPO aver chiamato it.next ().
Henrik Aasted Sørensen

0

Sebbene avessi già la risposta, ho pensato di aggiungere alcune informazioni.

Come hai menzionato esplicitamente le raccolte, non puoi utilizzare listIteratorper ottenere l'indice per tutti i tipi di raccolte.

Interfacce elenco : ArrayList, LinkedList, Vector e Stack.

Ha sia iterator()elistIterator()

Set interfaces - HashSet, LinkedHashSet, TreeSet e EnumSet.

Ha solo iterator()

Interfacce mappa : HashMap, LinkedHashMap, TreeMap e IdentityHashMap

Non ha iteratori, ma può essere iterato usando keySet()/ values()o entrySet()come keySet()eentrySet() restituisce Sete values()restituisceCollection .

Quindi è meglio usare iterators()con incremento continuo di un valore per ottenere l'indice corrente per qualsiasi tipo di raccolta.


-1

Questa sarebbe la soluzione più semplice!

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;

}

Testato su gcc-9 con -std=c++11 flag

Produzione:

0
1
2
3
4

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.