[Solved] How to get the value of flutter map by call by value

Question

Asked by Jungwon on November 18, 2021 (source).

I am developing a movie app using TMDB.

A total of 3 pieces of data are needed to create a reservation system.

1.MovieList's index

2.date's index

3.seat Satus

I've been trying to process this as a map.

//Seat Status total 200 Seat
List<bool> _seat = [];
for(int nIndex=0; nIndex<200; nIndex++){
      _seat.add(false);
    }

//Date index(total 7 days) + Seat status
Map _date = Map();
for(int nIndex=0; nIndex<7; nIndex++){
      _date[nIndex] = _seat.toList();
    }

//TMDB MovieList index
Map _movie = Map();
for(int nIndex=0; nIndex<MoviesList.length; nIndex++){
        _movie[nIndex] = _date;
    }

The value is entered normally as I want.

However, when one seat data is changed, all seat data in the map is changed.

I noticed that this is because the map and list references are input.

Do you know how to get a value by call by value rather than by call by reference?

 seat = List.filled(200, false, growable: true);
 date = List.generate(7, (_) => List.from(seat));
 movie = List.generate(length, (_) => List.from(date));

My code was like above.

for example

 movie[0][0][0] = false; // Change value
 print(movie[0][0][0]);  // result false
 print(movie[1][0][0]);  // result false

In this way, the values ​​change together.

Answer

Question answered by h8moss (source).

In order to make a new list reference with the same values as the previous one, you can call List.from.

So like this:

_date[nIndex] = List.from(_seat);

you can use a similar syntax with a map

_movie[nIndex] = Map.from(_date);

EDIT

It seems like this solution actually does not work, dart can use .from to copy a list, or even to copy a list of lists, but copying a list of a list of lists? That's too much man! It can't handle that, it will only copy up one level. Thankfully, solving this is simple once you know why it happens:

var seat = List.filled(3, false, growable: true);
var date = List.generate(4, (_) => List.from(seat));
var movie = List.generate(5, (_) => List.from(date.map((v) => 
List.from(v))));

movie[0][0][0] = true; // Change value
print(movie[0][0][0]); // true
print(movie[1][0][0]); // false (default value)

For the last one, instead of creating a new list from seat, I am first using map to copy each of the lists on to a new list, and then I am copying those new lists into a new list.

I believe that fixes the issue we were encountering

PS

This is a recommendation, if you don't care, you can stop reading now:

if you want to generate a list of 200 false values, you can use this syntax instead:

List<bool> _seat = List.filled(200, false, growable: true);

which makes for a shorter and more readable way to do the same thing.

When declaring a map, this syntax is preferred:

Map<int, List<bool>> _date = {};
Map<int, Map<int, List<bool>>> _movie = {};

I know it looks a bit gross, but it makes sure you don't add the wrong types to your map

And finally, why are you using a map in the first place? Your map behaves the exact same as a list because the key is an index, and you could generate said list using the generate constructor instead of a for loop, like this:

//Date index(total 7 days) + Seat status
List<List<bool>> _date = List.generate(7, (_) => List.from(_seat));

//TMDB MovieList index
List<List<List<bool>>> _movie = List.generate(
  MoviesList.length, (_) => List.from(_date));

Again, the syntax looks gross, that's because of all of the nested lists, probably better off making a class that can store the values in a more neat and type-safe way, but I lack the information to show you how you would write such a class.

DART DICTIONARY FLUTTER REFERENCE
SHARE: