En dardo hay cualquier equivalente al común:
enumerate(List) -> Iterator((index, value) => f)
or
List.enumerate() -> Iterator((index, value) => f)
or
List.map() -> Iterator((index, value) => f)
Parece que esta es la forma más fácil, pero todavía parece extraño que esta funcionalidad no exista.
Iterable<int>.generate(list.length).forEach( (index) => {
newList.add(list[index], index)
});
Editar:
Gracias a @ hemanth-raj pude encontrar la solución que estaba buscando. Lo pondré aquí para cualquiera que necesite hacer algo similar.
List<Widget> _buildWidgets(List<Object> list) {
return list
.asMap()
.map((index, value) =>
MapEntry(index, _buildWidget(index, value)))
.values
.toList();
}
Alternativamente, puede crear una función de generador síncrono para devolver un iterable
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
? ¿Esto es lo que quieres?List
? ¿Qué quieres decir? los documentos dicen: "Aplica f a cada par clave / valor del mapa. Llamar a f no debe agregar ni quitar claves del mapa".Respuestas:
Existe un
asMap
método que convierte la lista en un mapa donde las claves son el índice y los valores son el elemento en el índice. Por favor, eche un vistazo a los documentos aquí .Ejemplo:
List _sample = ['a','b','c']; _sample.asMap().forEach((index, value) => f);
¡Espero que esto ayude!
fuente
No hay una función incorporada para obtener el índice de iteración.
Si, como a mí, no le gusta la idea de construir un
Map
(la estructura de datos) solo para un índice simple, lo que probablemente quiera es unmap
(la función) que le da el índice. LlamémoslomapIndexed
(como en Kotlin):children: mapIndexed( list, (index, item) => Text("event_$index") ).toList();
La implementación de
mapIndexed
es simple: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; } }
fuente
mapIndexed
.asMap().forEach()
es esencialmente lo mismo que esto: vea mi respuesta.asMap()
que costará un bucle adicional para recuperar datos, por lo que no será eficiente como elmapIndexed()
anterior.Sobre la base de la respuesta de @Hemanth Raj.
Para convertirlo de nuevo, podrías hacer
List<String> _sample = ['a', 'b', 'c']; _sample.asMap().values.toList(); //returns ['a', 'b', 'c'];
O si necesita el índice para una función de mapeo, puede hacer esto:
_sample .asMap() .map((index, str) => MapEntry(index, str + index.toString())) .values .toList(); // returns ['a0', 'b1', 'c2']
fuente
A partir de Dart 2.7, puede utilizar
extension
para ampliar las funcionalidades enIterable
lugar de tener que escribir métodos auxiliaresextension 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++)); } }
Uso:
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
fuente
El paquete más de Lukas Renggli incluye muchas herramientas útiles, incluido "indexado", que hace exactamente lo que quieres. De los documentos:
indexed(['a', 'b'], offset: 1) .map((each) => '${each.index}: ${each.value}') .join(', ');
(Puede ignorar el argumento de compensación a menos que tenga antecedentes en Smalltalk :-).
fuente
Inicialmente pensé
['one', 'two', 'three'].asMap().forEach((index, value) { ... });
que sería realmente ineficiente porque parece que está convirtiendo la lista en un mapa. En realidad no lo es, la documentación dice que crea una vista inmutable de la lista. Verifiqué dos veces con eldart2js
de este código:void main() { final foo = ['one', 'two', 'three']; foo.asMap().forEach((idx, val) { print('$idx: $val'); }); }
¡Genera mucho código! Pero la esencia es esta:
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 };
¡Así que es lo suficientemente inteligente como para hacer lo eficiente! Muy inteligente.
Por supuesto, también puede usar un bucle for normal:
for (var index = 0; index < values.length; ++index) { final value = values[index];
fuente
Para mayor comodidad, puede utilizar este método de extensión.
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++; } } }
fuente
Utilice asMap para convertir la lista en mapa primero. El índice de elemento es la clave. El elemento se convierte en valor. Utilice entradas para asignar la clave y el valor a lo que desee.
List rawList = ["a", "b", "c"]; List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList(); print(argList);
Salida:
[0:a, 1:b, 2:c]
fuente