Comment obtenir l'index de la boucle actuelle lors de l'utilisation d'itérateur?

108

J'utilise un itérateur pour parcourir une collection et je souhaite obtenir l'index de l'élément actuel.

Comment puis je faire ça?

Mahmoud Saleh
la source
duplication possible de Y a
fin
1
@finnw Je ne pense pas qu'ils soient en double. Cette question se pose en utilisant Iterator, l'autre utilise la boucle for-each. Les deux questions sont résolues par une approche similaire, de sorte que les réponses sont dupliquées et non la question.
Robert

Réponses:

92

Utilisez votre propre variable et incrémentez-la dans la boucle.

Chris Diver
la source
6
Mais aussi voir la suggestion @ mateusz-dymczyk à propos de it.nextIndex(). Utile lorsque la collection est une liste.
noamtm
113

J'ai eu la même question et j'ai trouvé que l'utilisation d'un ListIterator fonctionnait. Similaire au test ci-dessus:

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

ListIterator iter = list.listIterator();

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

Assurez-vous d'appeler le nextIndex AVANT d'obtenir le next ().

Paul
la source
5
Merci d'avoir mentionné `` Assurez-vous d'appeler le prochainIndex AVANT d'obtenir le prochain () ''
Gangadhar JANNU
Merci, je ne savais pas ça avant. La mise en garde que je ferais est que ListIterator est bidirectionnel alors que Iterator est unidirectionnel. Tant que vous évitez de faire des allers-retours avec ce qui est en fait un curseur, vous devriez être en sécurité.
user2910265
28

Voici un moyen de le faire en utilisant votre propre variable et en la gardant concise:

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

Sortie (vous l'avez deviné):

0: zero
1: one
2: two

L'avantage est que vous n'incrémentez pas votre index dans la boucle (même si vous devez faire attention à n'appeler Iterator # next qu'une fois par boucle - faites-le simplement en haut).

Tom Clift
la source
3
Si vous créez l'itérateur vous-même, vous pouvez également utiliser un ListIterator et vous n'avez pas besoin de la variable int séparée.
Robert Klemme
1
Si vous utilisez une `` importation statique '' pour Arrays.asList, vous pouvez simplement écrireasList("zero", "one", "two")
karmakaze
c'est exactement la façon dont je l'ai fait avant de lire la réponse de Paul. Je découragerais fortement votre chemin, car je n'y vois aucun avantage. Pensez-vous qu'il y a un avantage (sauf celui mentionné). Pourquoi n'avez-vous pas utilisé une boucle for-each? Il n'est pas nécessaire de définir explicitement l'itérateur si vous utilisez votre propre variable.
Willi Mentzel
@progressive_overload juste si vous avez besoin d'un itérateur (comme par question, par exemple pour passer à la bibliothèque), que l'exemple ne montre pas. Dans cet exemple, vous avez une variable en dehors de la boucle et vous devez faire attention à appeler #next une fois. Dans l'exemple de Paul, il n'y a pas de variables en dehors de la boucle, mais vous devez faire attention à appeler #next et #nextIndex ensemble une fois (et en pratique, s'ils sont utilisés plus d'une fois, ils seraient tirés dans des variables locales, ce que cet exemple ne fait pas '' t montrer).
Tom Clift
23

Vous pouvez utiliser ListIteratorpour faire le comptage:

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);
}
Robert Klemme
la source
12

Quel genre de collection? S'il s'agit d'une implémentation de l'interface List, vous pouvez simplement utiliser it.nextIndex() - 1.

Mateusz Dymczyk
la source
4

Utilisez un ListIterator pour parcourir la collection. Si la collection n'est pas une liste pour commencer, utilisez d'abord Arrays.asList(Collection.toArray())pour la transformer en liste.

Jatin
la source
3

faites quelque chose comme ça:

        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.

        }
Ensoleillé
la source
4
L'appel de indexOf () nécessitera une analyse supplémentaire de la liste des périphériques. Il sera plus rapide d'incrémenter simplement un compteur local.
Greg Brown
1
D'accord. ce n'est pas la solution la plus efficace.
Ensoleillé
1
Il semble que vous ayez mis à jour l'exemple pour être plus efficace.
Greg Brown
2

Utilisez un int et incrémentez-le dans votre boucle.

Florian Reischl
la source
1

Regardez ici .

iterator.nextIndex()fournirait l'index de l'élément qui serait renvoyé par un appel ultérieur à next().

Gai
la source
L'interface Iterator n'a PAS la méthode nextIndex (). Vous devez utiliser explicitement un ListIterator pour cela, mais l'OP a posé des questions spécifiquement sur Iterator.
Fran Marzoa
0

Tout ce dont vous avez besoin pour l'utiliser le iterator.nextIndex () pour renvoyer l'index actuel sur lequel se trouve l'itérateur. Cela pourrait être un peu plus facile que d'utiliser votre propre variable de compteur (qui fonctionne toujours aussi).

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

Ce code parcourra la liste list1 un élément à la fois et imprimera le texte de l'élément, puis "est à l'index" puis il imprimera l'index dans lequel l'itérateur l'a trouvé. :)

Ryan
la source
1
En fait, votre code est désactivé par un car il tente d'afficher l'index APRÈS l'avoir appelé.next ().
Henrik Aasted Sørensen
0

Bien que vous ayez déjà eu la réponse, j'ai pensé à ajouter quelques informations.

Comme vous l'avez mentionné explicitement Collections, vous ne pouvez pas utiliser listIteratorpour obtenir l'index pour tous les types de collections.

Interfaces de liste - ArrayList, LinkedList, Vector et Stack.

A à la fois iterator()etlistIterator()

Définissez les interfaces - HashSet, LinkedHashSet, TreeSet et EnumSet.

A seulement iterator()

Interfaces cartographiques - HashMap, LinkedHashMap, TreeMap et IdentityHashMap

N'a pas d'itérateurs, mais peut être itéré à l'aide de keySet()/ values()ou entrySet()as keySet()et entrySet()renvoie Setet values()retourne Collection.

Il est donc préférable de l'utiliser iterators()avec une incrémentation continue d'une valeur pour obtenir l'index actuel de tout type de collection.

Vignesh Raja
la source
-1

Ce serait la solution la plus simple!

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;

}

Testé sur gcc-9 avec -std=c++11indicateur

Production:

0
1
2
3
4

Copain
la source