В дротике есть какой-нибудь эквивалент обыкновенному:
enumerate(List) -> Iterator((index, value) => f)
or
List.enumerate() -> Iterator((index, value) => f)
or
List.map() -> Iterator((index, value) => f)
Кажется, что это самый простой способ, но все же кажется странным, что такой функции не существует.
Iterable<int>.generate(list.length).forEach( (index) => {
newList.add(list[index], index)
});
Редактировать:
Благодаря @ hemanth-raj я смог найти решение, которое искал. Я помещу это здесь для всех, кому нужно сделать что-то подобное.
List<Widget> _buildWidgets(List<Object> list) {
return list
.asMap()
.map((index, value) =>
MapEntry(index, _buildWidget(index, value)))
.values
.toList();
}
В качестве альтернативы вы можете создать функцию синхронного генератора, чтобы возвращать итерируемый
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
? это то, что ты хочешь?List
? что вы имеете в виду? в документации сказано: «Применяет f к каждой паре ключ / значение карты. Вызов f не должен добавлять или удалять ключи с карты».Ответы:
Существует
asMap
метод, который преобразует список в карту, где ключи - это индекс, а значения - это элемент в индексе. Пожалуйста, взгляните на документацию здесь .Пример:
List _sample = ['a','b','c']; _sample.asMap().forEach((index, value) => f);
Надеюсь это поможет!
источник
Нет встроенной функции для получения индекса итерации.
Если вам, как и мне, не нравится идея построить
Map
(структуру данных) только для простого индекса, то, вероятно, вам нужнаmap
(функция), которая дает вам индекс. Назовем этоmapIndexed
(как в Котлине):children: mapIndexed( list, (index, item) => Text("event_$index") ).toList();
Реализация
mapIndexed
проста: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; } }
источник
mapIndexed
.asMap().forEach()
по сути то же самое - см. Мой ответ.asMap()
потребуется дополнительный цикл для извлечения данных, поэтому он не будет эффективным, какmapIndexed()
указано выше.Основываясь на ответе @Hemanth Raj.
Чтобы преобразовать его обратно, вы могли бы сделать
List<String> _sample = ['a', 'b', 'c']; _sample.asMap().values.toList(); //returns ['a', 'b', 'c'];
Или, если вам нужен индекс для функции сопоставления, вы можете сделать это:
_sample .asMap() .map((index, str) => MapEntry(index, str + index.toString())) .values .toList(); // returns ['a0', 'b1', 'c2']
источник
Начиная с Dart 2.7, вы можете использовать
extension
для расширения функциональных возможностейIterable
вместо написания вспомогательных методовextension 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++)); } }
Применение:
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
источник
Пакет Lukas Renggli more включает в себя множество полезных инструментов, включая «индексированные», которые делают именно то, что вы хотите. Из документов:
indexed(['a', 'b'], offset: 1) .map((each) => '${each.index}: ${each.value}') .join(', ');
(Вы можете игнорировать аргумент смещения, если у вас нет опыта работы с Smalltalk :-).
источник
Сначала я подумал,
['one', 'two', 'three'].asMap().forEach((index, value) { ... });
что это будет действительно неэффективно, потому что похоже, что он преобразует список в карту. На самом деле это не так - в документации говорится, что он создает неизменяемое представление списка. Я дважды проверилdart2js
этот код:void main() { final foo = ['one', 'two', 'three']; foo.asMap().forEach((idx, val) { print('$idx: $val'); }); }
Он генерирует много кода! Но суть такова:
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 };
Так что он достаточно умен, чтобы делать все эффективно! Довольно умно.
Конечно, вы также можете использовать обычный цикл for:
for (var index = 0; index < values.length; ++index) { final value = values[index];
источник
Для удобства вы можете использовать этот метод расширения.
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++; } } }
источник
Используйте asMap, чтобы сначала преобразовать список в карту. Индекс элемента - это ключ. Элемент становится ценностью. Используйте записи, чтобы сопоставить ключ и значение с чем угодно.
List rawList = ["a", "b", "c"]; List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList(); print(argList);
Выход:
[0:a, 1:b, 2:c]
источник