Enumerate or map through a list with index and value in Dart

In dart there any equivalent to the common:

enumerate(List) -> Iterator((index, value) => f) or List.enumerate() -> Iterator((index, value) => f) or List.map() -> Iterator((index, value) => f) 

It seems that this is the easiest way but it still seems strange that this functionality wouldn't exist.

Iterable<int>.generate(list.length).forEach( (index) => { newList.add(list[index], index) }); 
5

14 Answers

There is a asMap method which converts the list to a map where the keys are the index and values are the element at index. Please take a look at the docs here.

Example:

List _sample = ['a','b','c']; _sample.asMap().forEach((index, value) => f); 

Hope this helps!

6

You can use the mapIndexed or forEachIndexed extension methods from the collection package. Note that unlike javascript's array.map() or C#'s IEnumerable.Select(), the index is the first argument, not the second argument of the callback:

import 'package:collection/collection.dart'; void main() { final inputs = ['a', 'b', 'c', 'd', 'e', 'f']; final indexes = inputs.mapIndexed((index, element) => index).toList(); inputs.forEachIndexed((index, element) { print('index: $index, element: $element'); }); print(indexes); } 

Live Demo


Old answer

Starting with Dart 2.7, you can use extension methods to extend the functionalities of Iterable instead of having to write helper functions:

extension ExtendedIterable<E> on Iterable<E> { /// Like Iterable<T>.map but the callback has index as second argument Iterable<T> mapIndexed<T>(T Function(E e, int i) f) { var i = 0; return map((e) => f(e, i++)); } void forEachIndexed(void Function(E e, int i) f) { var i = 0; forEach((e) => f(e, i++)); } } 

Usage:

final inputs = ['a', 'b', 'c', 'd', 'e', 'f']; final results = inputs .mapIndexed((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.forEachIndexed((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 

Live Demo

10

There is no built-in function to get the iteration index.

If like me you don't like the idea to build a Map (the data structure) just for a simple index, what you probably want is a map (the function) which gives you the index. Let's call it mapIndexed (like in Kotlin):

children: mapIndexed( list, (index, item) => Text("event_$index") ).toList(); 

The implementation of mapIndexed is 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; } } 
6

Building on @Hemanth Raj answer.

To convert it back you could do

List<String> _sample = ['a', 'b', 'c']; _sample.asMap().values.toList(); //returns ['a', 'b', 'c']; 

Or if you needed the index for a mapping function you could do this:

_sample .asMap() .map((index, str) => MapEntry(index, str + index.toString())) .values .toList(); // returns ['a0', 'b1', 'c2'] 
0

I initially thought ['one', 'two', 'three'].asMap().forEach((index, value) { ... }); would be really inefficient because it looks like it is converting the list to a map. Actually it isn't - the documentation says it creates an immutable view of the list. I double checked with the dart2js of this code:

void main() { final foo = ['one', 'two', 'three']; foo.asMap().forEach((idx, val) { print('$idx: $val'); }); } 

It generates lot of code! But the gist is this:

 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 }; 

So it is smart enough to do the efficient thing! Pretty clever.

Of course you can also just use a normal for loop:

for (var index = 0; index < values.length; ++index) { final value = values[index]; 
1

Use asMap to convert List to map first. The index of element is the key. The element becomes value. Use entries to map the key and value to anything you want.

List rawList = ["a", "b", "c"]; List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList(); print(argList); 

Output:

[0:a, 1:b, 2:c] 
1

Lukas Renggli's more package includes many useful tools including 'indexed' which does exactly what you want. From the docs:

indexed(['a', 'b'], offset: 1) .map((each) => '${each.index}: ${each.value}') .join(', '); 

(You can ignore the offset argument unless you have a Smalltalk background :-).

You can use the mapIndexed extension from the collections package:

import 'package:collection/collection.dart'; void main() { final nums = [1, 2, 3]; final strs = nums.mapIndexed((index, element) => index.toString() + '_' + element.toString()).toList(); print(strs); // [0_1, 1_2, 2_3] } 
6

use -> mapIndexed(index, Element) Function

to map each element and its index to a new value.

import 'package:collection/collection.dart'; 

and use the map index as follows

(List).mapIndexed<Widget>( (mapIndex, mapElement) => Positioned( left: mapIndex.toDouble() * 5, child: Card( color: Colors.blue, child: Image.network( '${mapElement.ImageURL}', height: 80, width: 80)))) 

Please Refer:

For convenience you can use this extension method.

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++; } } } 
0

You can use Iterable.generate factory. The following code would map an Iterable using indexes and values.

extension IterableMapIndex<T> on Iterable<T> { Iterable<E> mapIndexed<E>(E f(int index, T t)) { return Iterable.generate(this.length, (index)=>f(index, elementAt(index))); } } 
0

Using dart collection package you can access various list extensions

one is mapIndexed:

Iterable<R> mapIndexed<R>(R Function(int, E) convert) 

list of all iterable extensions

1

You can create another variable to get index.

 int index = 0; array?.forEach((element) { // your code is here index++; // you should add this at end of the for loop }); 

package:quiver includes an enumerate function that is similar to Python's enumerate function.

(Note that although package:quiver isn't from the Dart team, it is owned and maintained by Google, and many of its contributors are members of Google's Dart and Flutter teams.)

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like