我正在尝试创建一个列表列表,以模仿Dart中2D阵列的功能,而我在找出如何使其工作时遇到了麻烦。
我最初使用List.forEach
来创建列表并填充它们,但是在每次循环之后,就好像我从未创建过列表一样。这是代码的样子:
currentMap = new List<List<int>>(height);
currentMap.forEach((e) {
e = new List<int>(width);
e.forEach((f) {
f = 1;
});
});
打印currentMap
会生成null
列表。这就是我现在所拥有的:
currentMap = new List<List<int>>(height);
for(int i = 0; i < height; i++) {
currentMap[i] = new List<int>(width);
for(int j = 0; j < width; j++) {
currentMap[i][j] = 1;
}
}
这完全符合我的预期。
我理解这可能是一个非常基本的问题,我假设forEach
不允许您修改元素,但我想要对此进行一些确认,Dart API文档没有指定除外用短语“苹果函数f到每个元素......”这对我来说可能不太清楚。
另外,我知道像List.filled()
构造函数这样的东西 - 这就是我开始构建其他功能的方式。
void function(MyObject o) {
o.x = 5;
}
但尝试更改o
指向的内容在退出函数后不会更改参数,例如:
void function(MyObject o) {
MyObject p = new MyObject();
o = p;
}
答案 0 :(得分:3)
Dart没有变量引用,所有元素都作为对象的引用传递,而不是传递给变量。 (换句话说,Dart纯粹是像Java和JavaScript一样的“分享呼叫”)。
这意味着e
回调的forEach
参数只是一个普通的局部变量,并且分配给它在回调之外没有任何影响。迭代器也是如此:它们返回迭代中的值,但之后没有引用回迭代。
当你执行“read-modify-write”时,你想要的是双循环。您从列表中读取值,修改它并使用列表的索引集运算符将其存储回列表中。
我知道你知道List.filled
,但是对于其他读者,我会给出一行代码来创建初始化为1
值的二维数组:
currentMap = new List.generate(height, (_) => new List.filled(width, 1));
答案 1 :(得分:2)
这是因为e
仅是对List
中currentMap
的引用,而不是currentMap
项目的引用。
您将引用的副本更新为List
,但此引用与currentMap
没有关联
在循环之后,e
只是收集垃圾。
答案 2 :(得分:1)
这是因为枚举器的工作原理,我相信因为枚举器是不可变的当你在foreach中处理它时,你无法修改集合项......删除成员等。
另见: