DEV Community

loading...

How To Use The map() Function In Dart

Benjamin Carlson
Creator of https://coffeeclass.io - a programming tutorial service.
Originally published at coffeeclass.io ・2 min read

The Problem

Recently, I was building a Flutter app and I needed to map over an array of users when a user logged in and check if their username, password, and security question answer matched what was
in the database (the userArray). I tried to do something like this:

var userArray = ['User 1', 'User 2', 'User 3'];

userArray
    .map((user) => {
            if (user == 'User 1')
            {
                // log user in
            } else {
                    // don't log user in
                }
            });
Enter fullscreen mode Exit fullscreen mode

Quick note: I removed some of my project specific logic and only included the important parts so it is easier to follow.

This code logs the user in if they are user 1. This looks like it should work, right? Unfortunately, it doesn't. It will not break either. Instead,
nothing will happen. This makes it hard to debug.

The Solution

The simple solution is to add .toList() to the end of the map statement.

var userArray = ['User 1', 'User 2', 'User 3'];

userArray
    .map((user) => {
            if (user == 'User 1')
            {
                // log user in
            } else {
                    // don't log user in
                }
            }).toList(); // add .toList() here!
Enter fullscreen mode Exit fullscreen mode

Why This Works

Unlike in JavaScript, in Dart when you .map() over an object, the Iterable that
is returned is lazy. This means it is not evaluated by calling .map(). To evaluate it, we need to call .toList(). You
can read more about this here.

If you want to quickly see this in action, open up DartPad and paste in the code below (with added print statements)
with and without .toList().

void main() {
  var userArray = ['User 1', 'User 2', 'User 3'];

userArray
    .map((user) => {
            if (user == 'User 1')
            {
                print('logging user 1 in!')
            } else {
                    print('Not user 1, can\'t log in!')
                }
            }).toList(); // Remove .toList() to see no output!
}
Enter fullscreen mode Exit fullscreen mode

From The Flutter Docs

.map()

Iterable<T> map<T>(T Function(String) f)

Returns a new lazy Iterable with elements that are created by calling f on each element of this Iterable in iteration order.

This method returns a view of the mapped elements. As long as the returned Iterable is not iterated over, the supplied function f will not be invoked. The transformed elements will not be cached. Iterating multiple times over the returned Iterable will invoke the supplied function f multiple times on the same element.

Methods on the returned iterable are allowed to omit calling f on any element where the result isn't needed. For example, elementAt may call f only once.

.toList()

List<Set<Set<void>>> toList({bool growable = true})

Creates a List containing the elements of this Iterable.

The elements are in iteration order. The list is fixed-length if growable is false.

Discussion (2)

Collapse
bjcarlson42 profile image
Benjamin Carlson Author

@ochrstn I use the result in the app I made but for this post I took out all of that logic and only included the relevant parts. The print statements are where I would use the list.

Collapse
ochrstn profile image
ochrstn

Could you please elaborate why you are using map and not forEach (api.dart.dev/stable/2.12.4/dart-co...) if you are not even using the resulting list?