mapWithIndex & friends

Los cuatro operadores que conocen el índice: map, filter, flatMap y fold con la posición del elemento como segundo argumento.

Iterable<B> mapWithIndex<A, B>(B Function(A a, int index) f, Iterable<A> iterable) Iterable<A> filterWithIndex<A>(bool Function(A a, int index) f, Iterable<A> iterable) Iterable<B> flatMapWithIndex<A, B>(Iterable<B> Function(A a, int index) f, Iterable<A> iterable) Acc foldWithIndex<A, Acc>(Acc seed, Acc Function(Acc acc, A a, int index) f, Iterable<A> iterable) // …Async for every one, and: Fx<R> Fx.mapWithIndex<R>(R Function(T a, int index) f) // chain

Lección

zipWithIndex ya te da la posición: empareja cada elemento con su índice y luego lees el par. Eso funciona, y es la herramienta correcta cuando el par es lo que quieres. Cuando no lo es, pagas un record por elemento y un cuerpo de callback escrito con p.$1 / p.$2 en vez de con nombres.

Estos cuatro reciben el índice directamente. No hay nada que reservar ni nada que desempaquetar, y la cadena dice lo que hace.

El índice cuenta la entrada de esa etapa. No es la posición del elemento en la fuente original: un filter por encima de mapWithIndex renumera lo que lo atraviesa, empezando otra vez en 0. El que hay que leer dos veces es filterWithIndex: su cuenta avanza también con los elementos que descarta, porque siguen siendo entrada. flatMapWithIndex cuenta elementos de la fuente, no emitidos, así que un iterable interno de cinco valores avanza el índice en uno.

Todos tienen su forma …Async, y la numeración sobrevive a concurrent: solapa los tirones aguas arriba pero los resuelve igualmente en orden, así que el elemento n recibe el índice n fueran cuales fueran las latencias. El contador vive además por iteración, así que volver a recorrer una cadena empieza otra vez en 0.

Una arruga de Dart en foldWithIndex: si el lambda del acumulador no lleva tipos, Acc se infiere como Object? y la aritmética deja de compilar. No es nada nuevo de aquí — el propio Iterable.fold de Dart se comporta igual — y la solución es la misma: escribe foldWithIndex<int>(…).

Demo 1 · mapWithIndex, y a qué sustituye

Demo 2 · filter, flatMap, fold — y asíncrono

Pruébalo tú

Ejercicio: numera a los que llegan a meta como 1st, 2nd, 3rd usando el índice.

Relacionado: indexed — la forma de pares, cuando el par es lo que quieres · map / filter / flatMap — los operadores que estos extienden · fold — la reducción con semilla · foldRight — el mismo fold desde el otro extremo