Im Dart gibt es ein Äquivalent zum Common:
enumerate(List) -> Iterator((index, value) => f)
or
List.enumerate() -> Iterator((index, value) => f)
or
List.map() -> Iterator((index, value) => f)
Es scheint, dass dies der einfachste Weg ist, aber es scheint immer noch seltsam, dass diese Funktionalität nicht existieren würde.
Iterable<int>.generate(list.length).forEach( (index) => {
newList.add(list[index], index)
});
Bearbeiten:
Dank @ hemanth-raj konnte ich die gesuchte Lösung finden. Ich werde dies hier für jeden einfügen, der etwas Ähnliches tun muss.
List<Widget> _buildWidgets(List<Object> list) {
return list
.asMap()
.map((index, value) =>
MapEntry(index, _buildWidget(index, value)))
.values
.toList();
}
Alternativ können Sie eine Synchrongeneratorfunktion erstellen, um eine iterable zurückzugeben
Iterable<MapEntry<int, T>> enumerate<T>(Iterable<T> items) sync* {
int index = 0;
for (T item in items) {
yield MapEntry(index, item);
index = index + 1;
}
}
//and use it like this.
var list = enumerate([0,1,3]).map((entry) => Text("index: ${entry.key}, value: ${entry.value}"));
Map#forEach
? ist es was du willst?List
? Was meinst du? In den Dokumenten heißt es: "Wendet f auf jedes Schlüssel / Wert-Paar der Karte an. Durch Aufrufen von f dürfen keine Schlüssel zur Karte hinzugefügt oder daraus entfernt werden."Antworten:
Es gibt eine
asMap
Methode, die die Liste in eine Karte konvertiert, wobei die Schlüssel der Index und die Werte das Element am Index sind. Bitte schauen Sie sich die Dokumente hier an .Beispiel:
List _sample = ['a','b','c']; _sample.asMap().forEach((index, value) => f);
Hoffe das hilft!
quelle
Es gibt keine integrierte Funktion zum Abrufen des Iterationsindex.
Wenn Sie wie ich die Idee nicht mögen, eine
Map
(die Datenstruktur) nur für einen einfachen Index zu erstellen , möchten Sie wahrscheinlich einemap
(die Funktion), die Ihnen den Index gibt. Nennen wir esmapIndexed
(wie in Kotlin):children: mapIndexed( list, (index, item) => Text("event_$index") ).toList();
Die Implementierung von
mapIndexed
ist einfach:Iterable<E> mapIndexed<E, T>( Iterable<T> items, E Function(int index, T item) f) sync* { var index = 0; for (final item in items) { yield f(index, item); index = index + 1; } }
quelle
mapIndexed
.asMap().forEach()
im Wesentlichen dasselbe ist - siehe meine Antwort.asMap()
, das Abrufen von Daten kostet eine zusätzliche Schleife, daher ist es nicht so effizient wiemapIndexed()
oben.Aufbauend auf der Antwort von @Hemanth Raj.
Um es zurück zu konvertieren, könnten Sie tun
List<String> _sample = ['a', 'b', 'c']; _sample.asMap().values.toList(); //returns ['a', 'b', 'c'];
Oder wenn Sie den Index für eine Zuordnungsfunktion benötigen, können Sie dies tun:
_sample .asMap() .map((index, str) => MapEntry(index, str + index.toString())) .values .toList(); // returns ['a0', 'b1', 'c2']
quelle
Ab Dart 2.7 können Sie
extension
die Funktionen erweitern,Iterable
anstatt Hilfsmethoden schreiben zu müssenextension ExtendedIterable<E> on Iterable<E> { /// Like Iterable<T>.map but callback have index as second argument Iterable<T> mapIndex<T>(T f(E e, int i)) { var i = 0; return this.map((e) => f(e, i++)); } void forEachIndex(void f(E e, int i)) { var i = 0; this.forEach((e) => f(e, i++)); } }
Verwendung:
final inputs = ['a', 'b', 'c', 'd', 'e', 'f']; final results = inputs .mapIndex((e, i) => 'item: $e, index: $i') .toList() .join('\n'); print(results); // item: a, index: 0 // item: b, index: 1 // item: c, index: 2 // item: d, index: 3 // item: e, index: 4 // item: f, index: 5
inputs.forEachIndex((e, i) => print('item: $e, index: $i')); // item: a, index: 0 // item: b, index: 1 // item: c, index: 2 // item: d, index: 3 // item: e, index: 4 // item: f, index: 5
quelle
Das weitere Paket von Lukas Renggli enthält viele nützliche Tools, darunter "indiziert", die genau das tun, was Sie wollen. Aus den Dokumenten:
indexed(['a', 'b'], offset: 1) .map((each) => '${each.index}: ${each.value}') .join(', ');
(Sie können das Offset-Argument ignorieren, es sei denn, Sie haben einen Smalltalk-Hintergrund :-).
quelle
Anfangs dachte ich, es
['one', 'two', 'three'].asMap().forEach((index, value) { ... });
wäre wirklich ineffizient, weil es so aussieht, als würde die Liste in eine Karte konvertiert. Eigentlich nicht - die Dokumentation besagt, dass eine unveränderliche Ansicht der Liste erstellt wird. Ich habe dasdart2js
mit diesem Code überprüft :void main() { final foo = ['one', 'two', 'three']; foo.asMap().forEach((idx, val) { print('$idx: $val'); }); }
Es generiert viel Code! Aber das Wesentliche ist:
main: function() { var foo = H.setRuntimeTypeInfo(["one", "two", "three"], ...); new H.ListMapView(foo, ...).forEach$1(0, new F.main_closure()); }, H.ListMapView.prototype = { forEach$1: function(_, f) { var t1, $length, t2, i; ... t1 = this._values; $length = t1.length; for (t2 = $length, i = 0; i < $length; ++i) { if (i >= t2) return H.ioore(t1, i); f.call$2(i, t1[i]); t2 = t1.length; if ($length !== t2) throw H.wrapException(P.ConcurrentModificationError$(t1)); } }, ... }, F.main_closure.prototype = { call$2: function(idx, val) { ... H.printString("" + idx + ": " + H.S(val)); }, $signature: 1 };
Es ist also klug genug, um das Effiziente zu tun! Ziemlich clever.
Natürlich können Sie auch einfach eine normale for-Schleife verwenden:
for (var index = 0; index < values.length; ++index) { final value = values[index];
quelle
Der Einfachheit halber können Sie diese Erweiterungsmethode verwenden.
extension CollectionUtil<T> on Iterable<T> { Iterable<E> mapIndexed<E, T>(E Function(int index, T item) transform) sync* { var index = 0; for (final item in this) { yield transform(index, item as T); index++; } } }
quelle
Verwenden Sie asMap , um List zuerst in Map zu konvertieren. Der Index des Elements ist der Schlüssel. Das Element wird zum Wert. Verwenden Sie Einträge , um den Schlüssel und den Wert nach Belieben zuzuordnen.
List rawList = ["a", "b", "c"]; List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList(); print(argList);
Ausgabe:
[0:a, 1:b, 2:c]
quelle