Dart/Flutter - Flatten a Nested List of Lists

This tutorial shows you how to flatten a nested List in Dart.

Sometimes, you may have a List whose elements are also a Lists. To make it easier to process the data, you may want to combine the elements to form a non-nested List. That kind of process is often referred to as flattening. There are several ways to do it in Dart. Below are the code examples which also work in Flutter.

Below are the nested Lists. The first one only has one level of nested, while the second one has more than one level of nested.

  final l1 = [[1, 2, 3], [4, 5], ['one', 'two', 'three']];
  final l2 = [[1, 2, ['x', 'y', 'z']], [4, 5], ['one', 'two', 'three']];

Using Loop

A conventional way to get the result is by using a for loop for iterating the outer List. First, create an empty List to store the result. In each iteration, add the elements of the inner List by using addAll. After the iteration is done, all elements should have been added to the result.

  List<T> flattenWithLoop<T>(List<List<T>> l) {
    final List<T> result = [];

    for (var elements in l) {
      result.addAll(elements);
    }

    return result;
  }
  print(flattenWithLoop(l1));

Output:

  [1, 2, 3, 4, 5, one, two, three]

Using expand

Dart's Iterable has an expand operator. It's used to expand each element of an Iterable into zero or more elements. Below is the usage example of the operator. The code is much shorter than the solution using for loop.

  List<T> flattenWithExpand<T>(List<List<T>> l) =>
      l.expand((i) => i).toList();
  print(flattenWithExpand(l1));

Output:

  [1, 2, 3, 4, 5, one, two, three]

Using Spread

Dart introduced spread operator (triple dot) in version 2.3. If you use Dart 2.3 or newer, it's possible to combine the elements using the spread operator.

  List<T> flattenWithSpread<T>(List<List<T>> l) =>
      [for (var elements in l) ...elements];
  print(flattenWithSpread(l1));

Output:

  [1, 2, 3, 4, 5, one, two, three]

Multi-Nested List

In the examples above, the inner Lists do not have another List. For cases where the nested level can be more than one or even unlimited, you may need to handle it recursively.

  List<T> flattenDeep<T>(List<dynamic> l) => [
    for (var element in l)
      if (element is! List) element else ...flattenDeep(element),
  ];
  print(flattenDeep(l2));

Output:

  [1, 2, x, y, z, 4, 5, one, two, three]

Summary

In this tutorial, we have learned how to combine a List of Lists into a non-nested one. You can use for loop, expand operator, or spread operator. It's also possible to handle multi-level nesting by using recursive calls.