Working with Iterables

By Syncfusion®, Inc. · Last updated

How to transform and question a list with map, where, fold, reduce, any, every, firstWhere, take and skip, and how to chain them.

What Is an Iterable?

Iterable = a collection of items you can go through one by one.

  • Every List is an Iterable.
  • So are the results of methods like map() and where().
  • You can use for-in on any Iterable.

This lesson is about asking questions of a whole list, and changing every item, in one short line.

Simple lesson: an Iterable is anything you can walk through, item by item.

A Real-World Example

The class teacher has everyone's marks: [45, 82, 91, 30, 67].

She asks:

  • "Give everyone 5 grace marks." That changes every item.
  • "Who passed, with 50 or more?" That keeps some items.
  • "What is the class total?" That squeezes all items into one number.
  • "Did anyone fail?" That asks one yes-or-no question.

Each question is one Iterable method. Switch the steps on and off:

Every Run box on this page runs on the course's Dart runner in your browser.

Watch for ( ) and [ ] in the output. They tell you whether you got an Iterable or a List.

What You Will Learn

In this lesson, you will learn:

  1. What an Iterable is, and why its results are "lazy".
  2. How to change every item with map() and expand().
  3. How to keep some items with where(), take() and skip().
  4. How to combine items with fold() and reduce().
  5. How to ask questions with any(), every() and firstWhere(), and chain them all.

Iterable vs List

The Result Prints with ( )

map gives an Iterable

void main() {
  var marks = [45, 82, 91];
  var withGrace = marks.map((m) => m + 5);
  print(withGrace);
  print(withGrace.toList());
}
  • ( ) = an Iterable.
  • [ ] = a List.
  • toList() = turns an Iterable into a List.

Lazy Results

Lazy = the work is not done until you actually use the result.

  • map() and where() only describe the work.
  • The work happens when you print, loop over, or call toList().
  • This saves time when you only need part of the result.

Call toList() when you need a real list: to use an index like [0], to add items, or to keep the result for later.

Simple lesson: most Iterable methods give a lazy Iterable, and toList() turns it into a List.

Transformation Methods

map()

map(f) = run function f on every item, and give back the new items.

  • Same number of items out as in.
  • The function decides what each new item looks like.

Change every item with map

void main() {
  var names = ['asha', 'ravi', 'priya'];
  print(names.map((n) => n.toUpperCase()).toList());

  var marks = [45, 82, 91];
  print(marks.map((m) => m >= 50 ? 'Pass' : 'Fail').toList());
}

expand()

expand(f) = each item becomes zero or more items, and they are all flattened into one Iterable.

Flatten groups into one list

void main() {
  var groups = [
    ['Asha', 'Ravi'],
    ['Priya'],
    ['Kiran', 'Meena', 'Imran'],
  ];
  var everyone = groups.expand((g) => g).toList();
  print(everyone);
  print(everyone.length);
}

Simple lesson: map changes each item into one new item, and expand can turn one item into many.

Filtering Methods

where()

where(test) = keep only the items for which test is true.

Keep only the items that pass a test

void main() {
  var marks = [45, 82, 91, 30, 67];
  var passed = marks.where((m) => m >= 50).toList();
  print(passed);
  print('${passed.length} students scored 50 or more.');

  var names = ['Asha', 'Ravi', 'Arjun', 'Priya'];
  print(names.where((n) => n.startsWith('A')).toList());
}

take() and skip()

  • take(n) = keep the first n items.
  • skip(n) = leave out the first n items, keep the rest.

The top three, and the rest

void main() {
  var rankList = ['Asha', 'Ravi', 'Priya', 'Kiran', 'Meena'];
  print(rankList.take(3).toList());
  print(rankList.skip(3).toList());
}

Simple lesson: where keeps the items that pass a test, and take or skip keep a part by position.

Combining Methods

fold()

fold(start, f) = start with a value, then combine it with each item, one by one, into one result.

How fold adds up the marks

  • sum = the result so far. Its first value is the 0 you gave.
  • m = the current item.

reduce()

reduce(f) = like fold, but it starts with the first item instead of a value you give.

Total and highest mark

void main() {
  var marks = [45, 82, 91, 30, 67];
  var total = marks.fold(0, (sum, m) => sum + m);
  var highest = marks.reduce((a, b) => a > b ? a : b);
  print('Total: $total');
  print('Highest: $highest');
  print('Average: ${(total / marks.length).toStringAsFixed(1)}');
}

fold or reduce?

Simple lesson: fold and reduce squeeze a whole list into one value, and fold is safe on an empty list.

Question Methods

any() and every()

  • any(test) = true if at least one item passes.
  • every(test) = true only if all items pass.

Did anyone fail? Did everyone attend?

void main() {
  var marks = [45, 82, 91, 30, 67];
  print(marks.any((m) => m < 35));
  print(marks.every((m) => m >= 35));

  var attendance = [true, true, true];
  print(attendance.every((present) => present));
}

firstWhere(), lastWhere() and singleWhere()

  • firstWhere(test) = the first item that passes.
  • lastWhere(test) = the last item that passes.
  • singleWhere(test) = the only item that passes. It crashes if there are zero or several.
  • Add orElse: () => value to give a value when nothing passes, instead of crashing.

Find items with a test

void main() {
  var marks = [45, 82, 91, 30, 67];
  print(marks.firstWhere((m) => m > 80));
  print(marks.lastWhere((m) => m > 80));
  print(marks.singleWhere((m) => m < 40));
  print(marks.firstWhere((m) => m == 100, orElse: () => -1));
}

Without orElse, a search that finds nothing crashes:

Nothing matched, and there is no orElse

void main() {
  var marks = [45, 82, 91];
  print(marks.firstWhere((m) => m == 100));
}

The error is Bad state: No element.

Simple lesson: any and every answer yes or no, and firstWhere finds an item, with orElse as a safe fallback.

Chaining Methods

Chaining = calling one method on the result of another, in one expression.

Read a chain from top to bottom, like a recipe:

A chain of steps

void main() {
  var marks = [45, 82, 91, 30, 67];
  var report = marks
      .where((m) => m >= 50)
      .map((m) => 'Scored $m')
      .toList();
  print(report);

  var bonusTotal = marks
      .map((m) => m + 5)
      .where((m) => m >= 50)
      .fold(0, (sum, m) => sum + m);
  print(bonusTotal);
}
  1. where keeps the marks that are 50 or more.
  2. map turns each one into a sentence.
  3. toList makes the result a real list.

Easy way to remember

  • map = change every item.
  • where = keep some items.
  • fold = squeeze everything into one value.
  • any / every = ask yes or no.
  • firstWhere = find one item.

Simple lesson: chain short steps, each doing one job, and read them from top to bottom.

TL;DR

  1. Iterable = anything you can walk through. Results print with ( ).

    • Lazy = work happens only when used. toList() makes a List.
  2. Change: map (one in, one out), expand (one in, many out).
  3. Keep: where (by test), take and skip (by position).
  4. Combine: fold(start, f) and reduce(f) give one value.

    • reduce crashes on an empty list.
  5. Ask: any, every, firstWhere, lastWhere, singleWhere (with orElse).

    • Chain them, one step per line.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Using [0] on a map resultmap gives a ListIt gives an Iterable. Call toList() firstAn error: no [] on Iterable.
Forgetting toList() before printingThe output will show [ ]An Iterable prints with ( )Output like (50, 87).
reduce on an empty listIt gives 0It crashesBad state: No element. Use fold.
firstWhere without orElseIt gives null when nothing matchesIt crashesBad state: No element.
where to change itemswhere transformswhere only keeps or dropsItems stay the same. Use map.
map to filtermap can drop itemsmap keeps the same countYou get false or null items. Use where.
One huge chain on one lineShorter is betterPut each step on its own lineCode nobody can read.

Check Yourself

Exercises

What to Remember

  • Every List is an Iterable. Iterable results print with ( ), and toList() makes a List.
  • map changes every item, and where keeps only the items that pass a test.
  • fold and reduce squeeze a list into one value. fold is safe on an empty list.
  • any and every ask yes-or-no questions, and firstWhere finds one item.
  • Chain short steps, one per line, and use orElse so a search never crashes.

Next: Sets. You will learn a collection that never holds the same value twice.