Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

flutter

dart

People also ask

How do you get the index of an item in a list in darts?

In Dart, the List class has 4 methods that can help you find the index of a specific element in a list: indexOf: Returns the first index of the first element in the list that equals a given element. Returns -1 if nothing is found. indexWhere: Returns the first index in the list that satisfies the given conditions.

How do I add a map to my list in Dart?

Declaring a Map using Map Literals To declare a map using map literals, you need to enclose the key-value pairs within a pair of curly brackets "{ }".


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!


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


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

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

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]