Gibt es ein Java-Äquivalent von Pythons "Enumerate" -Funktion?

In Python können Sie mit der enumerate Funktion eine Sequenz von (Index-, Wert-) Paaren iterieren. Beispielsweise:

 >>> numbers = ["zero", "one", "two"] >>> for i, s in enumerate(numbers): ... print i, s ... 0 zero 1 one 2 two 

Gibt es eine Möglichkeit, dies in Java zu tun?

9 Solutions collect form web for “Gibt es ein Java-Äquivalent von Pythons "Enumerate" -Funktion?”

Für Sammlungen, die die List Schnittstelle implementieren, können Sie die Methode listIterator() , um einen ListIterator . Der Iterator hat (unter anderem) zwei Methoden – nextIndex() , um den Index zu erhalten; Und next() , um den Wert zu bekommen (wie andere Iteratoren).

So könnte ein Java-Äquivalent des Python oben sein:

 List<String> numbers = Arrays.asList("zero", "one", "two"); ListIterator<String> it = numbers.listIterator(); while (it.hasNext()) { System.out.println(it.nextIndex() + " " + it.next()); } 

Die wie der Python ausgibt:

 0 zero 1 one 2 two 

Streng genommen, nein, da die Enumerate () – Funktion in Python eine Liste von Tupeln zurückgibt und Tupel in Java nicht existieren.

Wenn aber alles, was Sie interessieren, einen Index und einen Wert ausdruckt, dann können Sie dem Vorschlag von Richard Fearn folgen und nextIndex () und next () auf einem Iterator verwenden.

Beachten Sie außerdem, dass die Aufzählung () mit der allgemeineren zip () – Funktion (mit Python-Syntax) definiert werden kann:

 mylist = list("abcd") zip(range(len(mylist)), mylist) 

Ergibt [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Wenn du deine eigene Tupel- Klasse definierst (siehe Pairs oder 2-Tupel in Java als Startpunkt verwenden), dann könntest du sicherlich deine eigene Zip () – Funktion in Java schreiben, um sie zu benutzen (mit der Tuple-Klasse, die in der Verknüpfung):

 public static <X,Y> List<Tuple<X,Y>> zip(List<X> list_a, List<Y> list_b) { Iterator<X> xiter = list_a.iterator(); Iterator<Y> yiter = list_b.iterator(); List<Tuple<X,Y>> result = new LinkedList<Tuple<X,Y>>(); while (xiter.hasNext() && yiter.hasNext()) { result.add(new Tuple<X,Y>(xiter.next(), yiter.next())); } return result; } 

Und sobald du zip () hast, ist die Implementierung von Enumerate () trivial.

Bearbeiten: langsamer Tag bei der Arbeit, um es zu beenden:

 public static <X> List<Tuple<Integer,X>> enumerate (List<X> list_in) { List<Integer> nums = new ArrayList<Integer>(list_in.size()); for (int x = 0; x < list_in.size(); x++) { nums.add(Integer.valueOf(x)); } return zip (nums, list_in); } 

Bearbeiten 2: Wie in den Kommentaren zu dieser Frage darauf hingewiesen, ist das nicht ganz gleichwertig. Während es die gleichen Werte wie Pythons Aufzählung produziert, tut es dies nicht in der gleichen generativen Art und Weise, die Pythons Aufzählung tut. So könnte für große Sammlungen dieser Ansatz ziemlich unerschwinglich sein.

Ich finde das am ähnlichsten wie der Python-Ansatz.

Verwendung

 public static void main(String [] args) { List<String> strings = Arrays.asList("zero", "one", "two"); for(EnumeratedItem<String> stringItem : ListUtils.enumerate(strings)) { System.out.println(stringItem.index + " " + stringItem.item); } System.out.println(); for(EnumeratedItem<String> stringItem : ListUtils.enumerate(strings, 3)) { System.out.println(stringItem.index + " " + stringItem.item); } } 

Ausgabe

 0 zero 1 one 2 two 3 zero 4 one 5 two 

Eigenschaften

  • Arbeitet auf jedem iterable
  • Erstellt keine In-Memory-Liste Kopie (geeignet für große Listen)
  • Unterstützt native für jede Syntax
  • Akzeptiert einen Startparameter, der dem Index hinzugefügt werden kann

Implementierung

 import java.util.Iterator; public class ListUtils { public static class EnumeratedItem<T> { public T item; public int index; private EnumeratedItem(T item, int index) { this.item = item; this.index = index; } } private static class ListEnumerator<T> implements Iterable<EnumeratedItem<T>> { private Iterable<T> target; private int start; public ListEnumerator(Iterable<T> target, int start) { this.target = target; this.start = start; } @Override public Iterator<EnumeratedItem<T>> iterator() { final Iterator<T> targetIterator = target.iterator(); return new Iterator<EnumeratedItem<T>>() { int index = start; @Override public boolean hasNext() { return targetIterator.hasNext(); } @Override public EnumeratedItem<T> next() { EnumeratedItem<T> nextIndexedItem = new EnumeratedItem<T>(targetIterator.next(), index); index++; return nextIndexedItem; } }; } } public static <T> Iterable<EnumeratedItem<T>> enumerate(Iterable<T> iterable, int start) { return new ListEnumerator<T>(iterable, start); } public static <T> Iterable<EnumeratedItem<T>> enumerate(Iterable<T> iterable) { return enumerate(iterable, 0); } } 

Nach den Python-Dokumenten ( hier ), das ist das nächste, was man mit Java bekommen kann, und es ist nicht mehr ausführlich:

 String[] numbers = {"zero", "one", "two"} for (int i = 0; i < numbers.length; i++) // Note that length is a property of an array, not a function (hence the lack of () ) System.out.println(i + " " + numbers[i]); } 

Wenn du die List Klasse benutzen musst …

 List<String> numbers = Arrays.asList("zero", "one", "two"); for (int i = 0; i < numbers.size(); i++) { System.out.println(i + " " + numbers.get(i)); } 

* HINWEIS: Wenn Sie die Liste ändern müssen, während Sie es durchqueren, müssen Sie das Iterator-Objekt verwenden, da es die Möglichkeit hat, die Liste ohne Anhebung einer ConcurrentModificationException zu ändern.

 List<String> list = { "foo", "bar", "foobar"}; int i = 0; for (String str : list){ System.out.println(i++ + str ); } 

Nein. Vielleicht gibt es einige Bibliotheken für die Unterstützung einer solchen Funktionalität. Aber wenn Sie auf die Standardbibliotheken zurückgreifen, ist es Ihre Aufgabe zu zählen.

Ich denke, das sollte die Java-Funktionalität sein, die der Python ähnelt "Aufzählung" am meisten, obwohl es ziemlich kompliziert und ineffizient ist. Grundsätzlich nur die Liste der Indizes zu seinen Elementen, mit ListIterator oder Collector:

 List<String> list = new LinkedList<>(Arrays.asList("one", "two", "three", "four")); Map<Integer, String> enumeration = new Map<>(); ListIterator iter = list.listIterator(); while(iter.hasNext){ map.put(iter.nextIndex(), iter.next()); } 

Oder mit Lambda-Expression:

 Set<Integer, String> enumeration = IntStream.range(0, list.size()).boxed.collect(Collectors.toMap(index -> index, index -> list.get(index))); 

Dann kannst du es mit einer erweiterten für loop verwenden:

 for (Map.Entry<Integer, String> entry : enumeration.entrySet){ System.out.println(entry.getKey() + "\t" + entry.getValue()); } 

Jetzt mit Java 8s Stream API zusammen mit der kleinen ProtonPack Bibliothek, die StreamUtils bietet, kann es leicht erreicht werden.

Das erste Beispiel verwendet das gleiche für jede Notation wie in der Frage:

 Stream<String> numbers = Arrays.stream("zero one two".split(" ")); List<Indexed<String>> indexedNumbers = StreamUtils.zipWithIndex(numbers) .collect(Collectors.toList()); for (Indexed<String> indexed : indexedNumbers) { System.out.println(indexed.getIndex() + " " + indexed.getValue()); } 

Oben, obwohl nicht die faulen Auswertung wie in Python. Dazu müssen Sie die forEach() Stream API Methode verwenden:

 Stream<String> numbers = Arrays.stream("zero one two".split(" ")); StreamUtils.zipWithIndex(numbers) .forEach(n -> System.out.println(n.getIndex() + " " + n.getValue())); 

Die faulen Auswertung kann mit dem folgenden unendlichen Strom überprüft werden:

 Stream<Integer> infStream = Stream.iterate(0, i -> i++); StreamUtils.zipWithIndex(infStream) .limit(196) .forEach(n -> System.out.println(n.getIndex() + " " + n.getValue())); 

Durch die Kombination von Generika mit anonymen Schnittstellen können Sie im Wesentlichen eine Fabrikmethode für die Übergabe der Aufzählung erstellen. Der Enumerator-Callback verbirgt die Unzulänglichkeit des Iterators darunter.

 import java.util.Arrays; import java.util.List; import java.util.ListIterator; public class ListUtils2 { public static interface Enumerator<T> { void execute(int index, T value); }; public static final <T> void enumerate(final List<T> list, final Enumerator<T> enumerator) { for (ListIterator<T> it = list.listIterator(); it.hasNext();) { enumerator.execute(it.nextIndex(), it.next()); } } public static final void enumerate(final String[] arr, final Enumerator<String> enumerator) { enumerate(Arrays.asList(arr), enumerator); } public static void main(String[] args) { String[] names = { "John", "Paul", "George", "Ringo" }; enumerate(names, new Enumerator<String>() { @Override public void execute(int index, String value) { System.out.printf("[%d] %s%n", index, value); } }); } } 

Ergebnis

 [0] John [1] Paul [2] George [3] Ringo 

Erweiterte Gedanken

Karte, reduzieren, filtern

Ich habe dies einen Schritt weiter gemacht und erstellt Karte, reduzieren und filtern Funktionen basierend auf diesem Konzept.

Sowohl die Guave- als auch die Apache- Common-Collections-Abhängigkeiten beinhalten ähnliche Funktionen. Sie können sie nach Belieben überprüfen.

 import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.ListIterator; public class ListUtils { // ========================================================================= // Enumerate // ========================================================================= public static abstract interface Enumerator<T> { void execute(int index, T value, List<T> list); }; public static final <T> void enumerate(final List<T> list, final Enumerator<T> enumerator) { for (ListIterator<T> it = list.listIterator(); it.hasNext();) { enumerator.execute(it.nextIndex(), it.next(), list); } } // ========================================================================= // Map // ========================================================================= public static interface Transformer<T, U> { U execute(int index, T value, List<T> list); }; public static final <T, U> List<U> transform(final List<T> list, final Transformer<T, U> transformer) { List<U> result = new ArrayList<U>(); for (ListIterator<T> it = list.listIterator(); it.hasNext();) { result.add(transformer.execute(it.nextIndex(), it.next(), list)); } return result; } // ========================================================================= // Reduce // ========================================================================= public static interface Reducer<T, U> { U execute(int index, T value, U result, List<T> list); }; public static final <T, U> U reduce(final List<T> list, final Reducer<T, U> enumerator, U result) { for (ListIterator<T> it = list.listIterator(); it.hasNext();) { result = enumerator.execute(it.nextIndex(), it.next(), result, list); } return result; } // ========================================================================= // Filter // ========================================================================= public static interface Predicate<T> { boolean execute(int index, T value, List<T> list); }; public static final <T> List<T> filter(final List<T> list, final Predicate<T> predicate) { List<T> result = new ArrayList<T>(); for (ListIterator<T> it = list.listIterator(); it.hasNext();) { int index = it.nextIndex(); T value = it.next(); if (predicate.execute(index, value, list)) { result.add(value); } } return result; } // ========================================================================= // Predefined Methods // ========================================================================= // Enumerate public static <T> String printTuples(List<T> list) { StringBuffer buff = new StringBuffer(); enumerate(list, new Enumerator<T>() { @Override public void execute(int index, T value, List<T> list) { buff.append('(').append(index).append(", ") .append(value).append(')'); if (index < list.size() - 1) { buff.append(", "); } } }); return buff.toString(); } // Map public static List<String> intToHex(List<Integer> list) { return transform(list, new Transformer<Integer, String>() { @Override public String execute(int index, Integer value, List<Integer> list) { return String.format("0x%02X", value); } }); } // Reduce public static Integer sum(List<Integer> list) { return reduce(list, new Reducer<Integer, Integer>() { @Override public Integer execute(int index, Integer value, Integer result, List<Integer> list) { return result + value; } }, 0); } // Filter public static List<Integer> evenNumbers(List<Integer> list) { return filter(list, new Predicate<Integer>() { @Override public boolean execute(int index, Integer value, List<Integer> list) { return value % 2 == 0; } }); } // ========================================================================= // Driver // ========================================================================= public static void main(String[] args) { List<Integer> numbers = Arrays.asList(8, 6, 7, 5, 3, 0, 9); // Enumerate System.out.printf("%-10s: %s%n", "Enumerate", printTuples(numbers)); // Map System.out.printf("%-10s: %s%n", "Map", intToHex(numbers)); // Reduce System.out.printf("%-10s: %d%n", "Reduce", sum(numbers)); // Filter System.out.printf("%-10s: %s%n", "Filter", evenNumbers(numbers)); } } 
  • Effizient XML in Elasticsearch bringen
  • Gibt es so etwas wie CherryPy oder Cerise in der Java-Welt?
  • Wie finde ich alle bildbasierten PDFs?
  • Was ist das Äquivalent von Python's Celery Projekt für Java?
  • Sende korrekte Daten zwischen python und Java per Bluetooth
  • Konvertieren von Wort (.docx) zu docbook
  • JAXB-Äquivalent zur Erzeugung von c ++ - Klassen von xsd?
  • Enum mit Funktionen?
  • Unterschied zwischen Python selbst und Java das
  • Praktische Verwendung von Java-Klasse / JAR in Python?
  • Python-Dolmetscher in Jython
  • Python ist die beste Programmiersprache der Welt.