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

DartFlutter

Dart Problem Overview


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

Dart Solutions


Solution 1 - Dart

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!

Solution 2 - Dart

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

Solution 3 - Dart

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

Solution 4 - Dart

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']

Solution 5 - Dart

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]

Solution 6 - Dart

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

Solution 7 - Dart

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 :-).

Solution 8 - Dart

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

Solution 9 - Dart

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

Solution 10 - Dart

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: https://pub.dev/documentation/collection/latest/collection/IterableExtension/mapIndexed.html

Solution 11 - Dart

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

Solution 12 - Dart

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

Solution 13 - Dart

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

Solution 14 - Dart

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.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavid ReesView Question on Stackoverflow
Solution 1 - DartHemanth RajView Answer on Stackoverflow
Solution 2 - DartNearHuscarlView Answer on Stackoverflow
Solution 3 - DartVivienView Answer on Stackoverflow
Solution 4 - DartJørgen AndersenView Answer on Stackoverflow
Solution 5 - DartGary LeeView Answer on Stackoverflow
Solution 6 - DartTimmmmView Answer on Stackoverflow
Solution 7 - DartMichael DaviesView Answer on Stackoverflow
Solution 8 - Dartuser2233706View Answer on Stackoverflow
Solution 9 - Dartuser1998494View Answer on Stackoverflow
Solution 10 - DartTarishView Answer on Stackoverflow
Solution 11 - DartnavidView Answer on Stackoverflow
Solution 12 - DartHashem AboonajmiView Answer on Stackoverflow
Solution 13 - DartBIS TechView Answer on Stackoverflow
Solution 14 - DartjamesdlinView Answer on Stackoverflow