How to add maps to a list in dart when the map is nested?

Viewed 1569

I have a situation, where I have a map and its value will be updated on every iteration. I have to keep track of the changes in the map and so I have created a List<Map<String, dynamic>> as below and started adding the map to the list on every iteration.

To my surprise, the maps were added on every iteration but the values got updated to new values every time and did not have the record of the previous map. When I experimented the same with an integer, instead of a map the result was as expected and I am wondering why this was not the case of a map.

Please see below the scenario and help me with a solution to add the maps to the list.

    void main() {
  int count = 0;
  List<Map<String, dynamic>> listOfMoves = [];
 
  
  Map<String, dynamic> dummyMap = {
    '0': {
      '1': "a",
      '2': 'b',
      '3': 'c',
    },
    '1': {
      '1': "d",
      '2': 'e',
      '3': 'f',
    },
    '2': {
      '1': "g",
      '2': 'h',
      '3': 'i',
    }
    };
  
  for (var i = 0; i < 5; i++) {
    //these will happen on every iterations
    count++;
    dummyMap['1'] = '$count';
    dummyMap['2'] = '$count';
    dummyMap['3'] = '$count';



 //when the map is added here to the list, the values of map should be different on every iteration. But, I see in the final map all the list has the same value that was obtained in the final iteration

    listOfMoves.add(Map.from(dummyMap));

    print(listOfMoves.toString());
  
  }
}

Please check the output ins below doc for more details:

https://docs.google.com/document/d/1kKyKu1bd5nT5LwiaqmJX97ModCT6UiKCbSRRFLgGS8U/edit?usp=sharing

Actual Output:

[{0: {1: a, 2: b, 3: c}, 1: 1, 2: 1, 3: 1}]

[{0: {1: a, 2: b, 3: c}, 1: 2, 2: 2, 3: 2}, {0: {1: a, 2: b, 3: c}, 1: 2, 2: 2, 3: 2}]

[{0: {1: a, 2: b, 3: c}, 1: 3, 2: 3, 3: 3}, {0: {1: a, 2: b, 3: c}, 1: 3, 2: 3, 3: 3}, {0: {1: a, 2: b, 3: c}, 1: 3, 2: 3, 3: 3}]

[{0: {1: a, 2: b, 3: c}, 1: 4, 2: 4, 3: 4}, {0: {1: a, 2: b, 3: c}, 1: 4, 2: 4, 3: 4}, {0: {1: a, 2: b, 3: c}, 1: 4, 2: 4, 3: 4}, {0: {1: a, 2: b, 3: c}, 1: 4, 2: 4, 3: 4}]

[{0: {1: a, 2: b, 3: c}, 1: 5, 2: 5, 3: 5}, {0: {1: a, 2: b, 3: c}, 1: 5, 2: 5, 3: 5}, {0: {1: a, 2: b, 3: c}, 1: 5, 2: 5, 3: 5}, {0: {1: a, 2: b, 3: c}, 1: 5, 2: 5, 3: 5}, {0: {1: a, 2: b, 3: c}, 1: 5, 2: 5, 3: 5}]

Expected Output:

[{0: {1: a, 2: b, 3: c}, 1: 1, 2: 1, 3: 1}]

[{0: {1: a, 2: b, 3: c}, 1: 1, 2: 1, 3: 1}, {0: {1: a, 2: b, 3: c}, 1: 2, 2: 2, 3: 2}]

[{0: {1: a, 2: b, 3: c}, 1: 1, 2: 1, 3: 1}, {0: {1: a, 2: b, 3: c}, 1: 2, 2: 2, 3: 2}, {0: {1: a, 2: b, 3: c}, 1: 3, 2: 3, 3: 3}]

[{0: {1: a, 2: b, 3: c}, 1: 1, 2: 1, 3: 1}, {0: {1: a, 2: b, 3: c}, 1: 2, 2: 2, 3: 2}, {0: {1: a, 2: b, 3: c}, 1: 3, 2: 3, 3: 3}, {0: {1: a, 2: b, 3: c}, 1: 4, 2: 4, 3: 4}]

[{0: {1: a, 2: b, 3: c}, 1: 1, 2: 1, 3: 1}, {0: {1: a, 2: b, 3: c}, 1: 2, 2: 2, 3: 2}, {0: {1: a, 2: b, 3: c}, 1: 3, 2: 3, 3: 3},{0: {1: a, 2: b, 3: c}, 1: 4, 2: 4, 3: 4}, {0: {1: a, 2: b, 3: c}, 1: 5, 2: 5, 3: 5}]
1 Answers

This is due to how dart passes arguments, Primitives (like int, bool, and num) are passed by value and Objects are passed by reference, see this discussion

So in your code you are passing the reference of dummyMap and the value of count:

void main() {
  int count = 0;
  List<Map<String, dynamic>> listOfMoves = [];
  List<int> countOfMoves = [];
  
  Map<String, dynamic> dummyMap = {
    '1': "one",
    '2': 'two',
    '3': 'three',
    };
  
  for (var i = 0; i < 5; i++) {
    //these will happen on every iterations
    count++;
    dummyMap['1'] = '$count';
    dummyMap['2'] = '$count';
    dummyMap['3'] = '$count';

    countOfMoves.add(count);
    listOfMoves.add(dummyMap);

    print(listOfMoves.toString());
    print(countOfMoves.toString());
  }
}

To fix this you could create a copy of the dummyMap to give it a different reference by changing this line:

listOfMoves.add(dummyMap);

to

listOfMoves.add({...dummyMap});

using the literal dictionary and spread operator

or classic version:

listOfMoves.add(Map.from(dummyMap));

then you will get:

[{1: 1, 2: 1, 3: 1}]
[{1: 1, 2: 1, 3: 1}, {1: 2, 2: 2, 3: 2}]
[{1: 1, 2: 1, 3: 1}, {1: 2, 2: 2, 3: 2}, {1: 3, 2: 3, 3: 3}]
[{1: 1, 2: 1, 3: 1}, {1: 2, 2: 2, 3: 2}, {1: 3, 2: 3, 3: 3}, {1: 4, 2: 4, 3: 4}]
[{1: 1, 2: 1, 3: 1}, {1: 2, 2: 2, 3: 2}, {1: 3, 2: 3, 3: 3}, {1: 4, 2: 4, 3: 4}, {1: 5, 2: 5, 3: 5}]

This question is similar but not quite the same.

Related