Wie erhalte ich den aktuellen Schleifenindex bei Verwendung von Iterator?

107

Ich verwende einen Iterator, um eine Sammlung zu durchlaufen, und möchte den Index des aktuellen Elements abrufen.

Wie kann ich das machen?

Mahmoud Saleh
quelle
1
@ Finnw Ich glaube nicht, dass sie doppelt sind. Diese Frage wird mit Iterator gestellt, die andere mit for-each-Schleife. Beide Fragen werden auf ähnliche Weise gelöst, daher sind die Antworten doppelt und nicht die Frage.
Robert

Antworten:

92

Verwenden Sie Ihre eigene Variable und erhöhen Sie sie in der Schleife.

Chris Diver
quelle
6
Aber siehe auch @ mateusz-dymczyk Vorschlag über it.nextIndex(). Nützlich, wenn die Sammlung eine Liste ist.
Noamtm
113

Ich hatte die gleiche Frage und fand mit einem ListIterator funktioniert. Ähnlich wie beim obigen Test:

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

ListIterator iter = list.listIterator();

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

Stellen Sie sicher, dass Sie den nextIndex aufrufen, bevor Sie den next () erhalten.

Paul
quelle
5
Vielen Dank für die Erwähnung "Stellen Sie sicher, dass Sie den nächsten Index aufrufen, bevor Sie tatsächlich den nächsten () erhalten"
Gangadhar JANNU
Danke, das wusste ich vorher nicht. Die Warnung, die ich machen würde, ist, dass ListIterator bidirektional ist, während Iterator unidirektional ist. Solange Sie vermeiden, sich mit einem Cursor hin und her zu bewegen, sollten Sie in Sicherheit sein.
user2910265
28

Hier ist eine Möglichkeit, dies mit Ihrer eigenen Variablen zu tun und sie kurz zu halten:

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

Ausgabe (Sie haben es erraten):

0: zero
1: one
2: two

Der Vorteil ist, dass Sie Ihren Index nicht innerhalb der Schleife erhöhen (obwohl Sie darauf achten müssen, Iterator # nur einmal pro Schleife aufzurufen - tun Sie dies einfach oben).

Tom Clift
quelle
3
Wenn Sie den Iterator selbst erstellen, können Sie auch einen ListIterator verwenden und benötigen keine separate int-Variable.
Robert Klemme
1
Wenn Sie einen 'statischen Import' für Arrays.asList verwenden, können Sie einfach schreibenasList("zero", "one", "two")
karmakaze
Genau so habe ich es gemacht, bevor ich die Antwort von Paul gelesen habe. Ich würde Ihren Weg stark entmutigen, weil ich keinen Vorteil dafür sehe. Glauben Sie, dass es einen Vorteil gibt (mit Ausnahme des genannten)? Warum haben Sie nicht für jede Schleife eine verwendet? Eine explizite Definition des Iterators ist nicht erforderlich, wenn Sie eine eigene Variable verwenden.
Willi Mentzel
@progressive_overload nur, wenn Sie einen Iterator benötigen (gemäß Frage, z. B. um an die Bibliothek zu übergeben), den das Beispiel nicht zeigt. In diesem Beispiel haben Sie eine Variable außerhalb der Schleife und müssen darauf achten, #next einmal aufzurufen. In Pauls Beispiel gibt es keine Variablen außerhalb der Schleife, aber Sie müssen darauf achten, #next und #nextIndex einmal zusammen aufzurufen (und in der Praxis werden sie bei mehrmaliger Verwendung in lokale Variablen gezogen, was in diesem Beispiel nicht der Fall ist. ' t zeigen).
Tom Clift
23

Sie können verwenden ListIterator, um zu zählen:

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
quelle
12

Was für eine Sammlung? Wenn es sich um eine Implementierung der List-Schnittstelle handelt, können Sie diese einfach verwenden it.nextIndex() - 1.

Mateusz Dymczyk
quelle
4

Verwenden Sie einen ListIterator , um die Sammlung zu durchlaufen. Wenn es sich bei der Sammlung zunächst nicht um eine Liste handelt, wird Arrays.asList(Collection.toArray())sie zunächst in eine Liste umgewandelt.

Jatin
quelle
3

mach einfach so etwas:

        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.

        }
Sonnig
quelle
4
Das Aufrufen von indexOf () erfordert einen zusätzlichen Scan der Geräteliste. Es ist schneller, einfach einen lokalen Zähler zu erhöhen.
Greg Brown
1
einverstanden. Dies ist nicht die effizienteste Lösung.
Sunny
1
Sieht so aus, als hätten Sie das Beispiel aktualisiert, um effizienter zu sein.
Greg Brown
2

Verwenden Sie ein int und erhöhen Sie es innerhalb Ihrer Schleife.

Florian Reischl
quelle
1

Siehe hier .

iterator.nextIndex()würde einen Index des Elements bereitstellen, das durch einen nachfolgenden Aufruf von zurückgegeben würde next().

Lustig
quelle
Der Schnittstellen-Iterator verfügt NICHT über die Methode nextIndex (). Sie müssen dafür explizit einen ListIterator verwenden, aber das OP hat speziell nach Iterator gefragt.
Fran Marzoa
0

Alles, was Sie brauchen, ist iterator.nextIndex (), um den aktuellen Index zurückzugeben, auf dem sich der Iterator befindet. Dies könnte etwas einfacher sein als die Verwendung einer eigenen Zählervariablen (die auch noch funktioniert).

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

Dieser Code durchläuft die Liste1 einzeln und druckt den Text des Elements. Dann wird "ist am Index" und dann der Index gedruckt, bei dem der Iterator ihn gefunden hat. :) :)

Ryan
quelle
1
Tatsächlich ist Ihr Code um eins deaktiviert, da er versucht, den Index nach dem Aufruf von it.next () anzuzeigen.
Henrik Aasted Sørensen
0

Obwohl Sie bereits die Antwort hatten, dachten Sie daran, einige Informationen hinzuzufügen.

Wie Sie bereits erwähnt haben, können Sie listIteratorden Index nicht für alle Arten von Sammlungen abrufen.

Liste Schnittstellen - Arraylist, LinkedList, Vektor und Stapel.

Hat beide iterator()undlistIterator()

Festlegen von Schnittstellen - HashSet, LinkedHashSet, TreeSet und EnumSet.

Hat nur iterator()

Karte Schnittstellen - HashMap, LinkedHashMap, TreeMap und IdentityHashMap

Hat keine Iteratoren, kann aber mit keySet()/ values()oder entrySet()as keySet()und entrySet()return Setund values()return iteriert werden Collection.

Daher ist es besser, iterators()mit einem kontinuierlichen Inkrement eines Werts den aktuellen Index für jeden Sammlungstyp abzurufen.

Vignesh Raja
quelle
-1

Dies wäre die einfachste Lösung!

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;

}

Getestet auf gcc-9 mit -std=c++11Flagge

Ausgabe:

0
1
2
3
4

Kumpel
quelle