W dart jest jakikolwiek odpowiednik wspólnego:
enumerate(List) -> Iterator((index, value) => f)
or
List.enumerate() -> Iterator((index, value) => f)
or
List.map() -> Iterator((index, value) => f)
Wydaje się, że to najłatwiejszy sposób, ale nadal wydaje się dziwne, że taka funkcjonalność nie istniała.
Iterable<int>.generate(list.length).forEach( (index) => {
newList.add(list[index], index)
});
Edytować:
Dzięki @ hemanth-raj udało mi się znaleźć rozwiązanie, którego szukałem. Umieszczę to tutaj dla każdego, kto musi zrobić coś podobnego.
List<Widget> _buildWidgets(List<Object> list) {
return list
.asMap()
.map((index, value) =>
MapEntry(index, _buildWidget(index, value)))
.values
.toList();
}
Alternatywnie możesz utworzyć synchroniczną funkcję generatora, aby zwrócić iterowalną
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
? czy tego chceszList
? co masz na myśli? Dokumentacja mówi: „Stosuje f do każdej pary klucz / wartość mapy. Wywołanie f nie może dodawać ani usuwać kluczy z mapy”.Odpowiedzi:
Istnieje
asMap
metoda, która konwertuje listę na mapę, w której klucze są indeksem, a wartości są elementem w indeksie. Proszę spojrzeć na dokumenty tutaj .Przykład:
List _sample = ['a','b','c']; _sample.asMap().forEach((index, value) => f);
Mam nadzieję że to pomoże!
źródło
Nie ma wbudowanej funkcji do uzyskania indeksu iteracji.
Jeśli tak jak ja nie podoba ci się pomysł zbudowania
Map
(struktury danych) tylko dla prostego indeksu, prawdopodobnie potrzebujeszmap
(funkcji), która daje ci indeks. Nazwijmy tomapIndexed
(jak w Kotlinie):children: mapIndexed( list, (index, item) => Text("event_$index") ).toList();
Wdrożenie
mapIndexed
jest proste: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; } }
źródło
mapIndexed
.asMap().forEach()
zasadzie jest to to samo - zobacz moją odpowiedź.asMap()
będzie kosztować dodatkową pętlę do pobierania danych, więc nie będzie wydajna jakmapIndexed()
powyżej.Opierając się na odpowiedzi @Hemanth Raj.
Aby go przekonwertować, możesz zrobić
List<String> _sample = ['a', 'b', 'c']; _sample.asMap().values.toList(); //returns ['a', 'b', 'c'];
Lub jeśli potrzebujesz indeksu do funkcji mapowania, możesz to zrobić:
_sample .asMap() .map((index, str) => MapEntry(index, str + index.toString())) .values .toList(); // returns ['a0', 'b1', 'c2']
źródło
Począwszy od Dart 2.7, możesz
extension
rozszerzyć funkcjonalnośćIterable
zamiast pisać metody pomocniczeextension 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++)); } }
Stosowanie:
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
źródło
Więcej w pakiecie Lukasa Renggliego zawiera wiele przydatnych narzędzi, w tym „indeksowane”, które robi dokładnie to, co chcesz. Z dokumentów:
indexed(['a', 'b'], offset: 1) .map((each) => '${each.index}: ${each.value}') .join(', ');
(Możesz zignorować argument przesunięcia, chyba że masz tło Smalltalk :-).
źródło
Początkowo myślałem
['one', 'two', 'three'].asMap().forEach((index, value) { ... });
, że byłoby to naprawdę nieefektywne, ponieważ wygląda na to, że konwertuje listę na mapę. W rzeczywistości tak nie jest - dokumentacja mówi, że tworzy niezmienny widok listy. Dokładnie sprawdziłemdart2js
ten kod:void main() { final foo = ['one', 'two', 'three']; foo.asMap().forEach((idx, val) { print('$idx: $val'); }); }
Generuje dużo kodu! Ale istota jest taka:
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 };
Jest więc wystarczająco inteligentny, aby robić rzeczy wydajne! Całkiem sprytnie.
Oczywiście możesz też użyć zwykłej pętli for:
for (var index = 0; index < values.length; ++index) { final value = values[index];
źródło
Dla wygody możesz skorzystać z tej metody rozszerzenia.
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++; } } }
źródło
Użyj asMap, aby najpierw przekonwertować List do mapy. Indeks elementu jest kluczem. Element staje się wartością. Użyj wpisów, aby zmapować klucz i wartość na cokolwiek chcesz.
List rawList = ["a", "b", "c"]; List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList(); print(argList);
Wynik:
[0:a, 1:b, 2:c]
źródło