1
votes

To solve a problem, I'm pre-populating a Map and then trying to pull the answer out of the map later when needed.

The map is populated like this:

var cycles = {
  [0, 0, 0, 0, 0, 0, 0, 0] : [[0, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 1, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 1, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0]],
  [0, 0, 0, 0, 0, 0, 0, 1] : [[0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 1, 0], [0, 1, 1, 1, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 1, 1, 1, 0, 0], [0, 1, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 1, 0, 1, 0], [0, 1, 0, 0, 1, 1, 1, 0], [0, 1, 0, 0, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 0, 0]],
  ...
};

Later, a function is called like this:

print(pullAnswerFromMap([1,0,0,1,0,0,1,0], 1000000000));

Where the pullAnswerFromMap function is defined as:

return cycles[cells][N % 14 == 0 ? 14 : N % 14];

The cycles map will have every possible key - all 256 lists of 8 bits.

But when running the code with an example to test, I get the following:

Unhandled exception:
NoSuchMethodError: The method '[]' was called on null.
Receiver: null

So, before the return statement, I added print(cycles); - The map prints just fine. All data is there. Then I added print(cycles[[1,0,0,1,0,0,1,0]]); which prints null, even though I can see that it exists in the map in the output from the previous print statement.

So it seems as though the key isn't based on the equality of the lists, but somehow on the specific instance (memory address?) of the list. A new list with the same elements in the same order will return null when trying to retrieve the value from the map.

My question is: How can I fix this so that cycles[[1,0,0,1,0,0,1,0]] doesn't return null and instead returns the List<List<int>> that it is associated with?

2

2 Answers

1
votes

The only way I see being able to do this is to reference the keys through cycles.keys. So cycles[cycles.keys.first] works perfectly and returns what's necessary. So to achieve what you want, you could do a search function that finds the key that you need.

Example:

void main() {
  bool compareList(List<int> list1, List<int> list2) {
    for(int x = 0; x < list1.length; x++) {
      if(list1[x] != list2[x]) {
        return false;
      }
    }
    return true;
  }
  
  List<int> key;
  List<int> input = [0, 0, 0, 0, 0, 0, 0, 1];
  for(int x = 0; x < input.length; x++) {
    if(compareList(cycles.keys.elementAt(x), input)) {
      key = cycles.keys.elementAt(x);
      break;
    }
  }
  
  print(cycles[key]);
}

Map<List<int>, List<List<int>>> cycles = {
  [0, 0, 0, 0, 0, 0, 0, 0] : [[0, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 1, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 1, 0, 1, 0], [0, 1, 1, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0]],
  [0, 0, 0, 0, 0, 0, 0, 1] : [[0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 1, 0], [0, 1, 1, 1, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 1, 1, 1, 1, 0], [0, 0, 0, 1, 1, 1, 0, 0], [0, 1, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 1, 0, 1, 0], [0, 1, 0, 0, 1, 1, 1, 0], [0, 1, 0, 0, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 0, 0]],
};
1
votes

So it seems as though the key isn't based on the equality of the lists, but somehow on the specific instance (memory address?) of the list.

Map (which by default is a LinkedHashMap) uses the key type's operator == and hashCode to determine if two keys are the same. List does not override those; two separate List instances will never compare equal, and therefore your attempts to look up Map values from a List key will always fail.

A couple of ways to fix that would be:

  • Explicitly use the LinkedHashMap constructor so that you can provide your own callbacks for computing hash codes and for determining if two keys are equal.

  • Create a custom class for the Map key, where your class has a List<int> member and overrides operator == and hashCode appropriately.

See How can I compare Lists for equality in Dart? for how to do a deep equality check on Lists.