【问题标题】:Using List<int> as the key for a Map always returns null使用 List<int> 作为 Map 的键总是返回 null
【发布时间】:2020-07-03 18:57:43
【问题描述】:

为了解决一个问题,我预先填充了一个地图,然后在需要时尝试从地图中提取答案。

地图是这样填充的:

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]],
  ...
};

后来,一个函数是这样调用的:

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

其中pullAnswerFromMap函数定义为:

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

cycles 映射将包含所有可能的键 - 所有 256 个 8 位列表。

但是当运行带有示例的代码进行测试时,我得到以下信息:

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

所以,在返回语句之前,我添加了print(cycles); - 地图打印得很好。所有数据都在那里。 然后我添加了print(cycles[[1,0,0,1,0,0,1,0]]);,它打印了null,尽管我可以看到它存在于上一个打印语句输出的映射中。

所以似乎密钥不是基于列表的相等性,而是基于列表的特定实例(内存地址?)。尝试从地图中检索值时,具有相同顺序的相同元素的新列表将返回 null。

我的问题是:我该如何解决这个问题,以便 cycles[[1,0,0,1,0,0,1,0]] 不返回 null 而是返回与之关联的 List&lt;List&lt;int&gt;&gt;

【问题讨论】:

    标签: dart


    【解决方案1】:

    所以似乎键不是基于列表的相等性,而是基于列表的特定实例(内存地址?)。

    Map(默认为LinkedHashMap)使用密钥类型的operator ==hashCode 来确定两个密钥是否相同。 List 不会覆盖那些;两个单独的 List 实例永远不会比较相等,因此您从 List 键中查找 Map 值的尝试将始终失败。

    解决这个问题的几种方法是:

    • 显式使用the LinkedHashMap constructor,以便您可以提供自己的回调来计算哈希码并确定两个键是否相等。

    • Map 键创建一个自定义类,其中您的类有一个List&lt;int&gt; 成员并适当地覆盖operator ==hashCode

    请参阅 How can I compare Lists for equality in Dart?,了解如何对 Lists 进行深度相等检查。

    【讨论】:

      【解决方案2】:

      我认为能够做到这一点的唯一方法是通过cycles.keys 引用密钥。所以cycles[cycles.keys.first] 可以完美运行并返回必要的内容。所以要实现你想要的,你可以做一个搜索功能来找到你需要的键。

      例子:

      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]],
      };
      

      【讨论】:

      • 我不知道发生了什么,但我没有看到示例
      • @loganrussell48 我添加了示例
      猜你喜欢
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 2011-07-01
      • 2021-05-24
      • 2018-02-16
      相关资源
      最近更新 更多