为什么 map 不起作用但 foreach 可以?
Why is map not working but foreach is?
这个forEach
工作得很好
var newMarkers = new List<Marker>();
providers.forEach((p) {
var marker = markerFrom(p);
newMarkers.add(marker);
print("got one");
});
_markers = newMarkers;
但是这个 map
与 forEach
放在完全相同的位置时永远不会被调用:
_markers = providers.map((p) => markerFrom(p));
此外,这是 markerFrom
方法:
Marker markerFrom(FoodProvider provider) {
var marker = new Marker(new MarkerOptions()
..map = _map
..position = new LatLng(provider.latitude, provider.longitude)
..title = provider.name
..icon = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png'
);
var infoWindow = new InfoWindow(new InfoWindowOptions()..content = marker.title);
marker.onClick.listen((e) {
infoWindow.open(_map, marker);
});
return marker;
}
Iterable
上的 map
函数是 lazy。它只是围绕原始 Iterable
创建了一个包装器,但在您开始迭代之前它实际上并没有做任何事情。
这是一件好事,即使如果您习惯了来自其他语言的热切map
功能,这可能会让您感到惊讶。这意味着您可以组合对可迭代对象的操作,例如:
listOfStrings
.map((x) => complicatedOperationOnString(x))
.take(2)
.forEach(print);
这只对前两个字符串进行了复杂的操作。
如果你想要一个标记列表,你需要在 map
:
之后调用 toList
_markers = providers.map(markerFrom).toList();
一般来说,当传递给 map
的函数具有您希望只发生一次的副作用时,您应该非常小心。如果你多次重复 map
的结果,每次都会发生这种效果,所以如果你这样做:
_markers = providers.map(markerFrom);
int count = _markers.length;
_markers.forEach((marker) { doSomething(marker); });
你会 冒 副作用发生两次的风险,一次是 length
,一次是 forEach
,两者都会重复 _markers
。
它并不总是发生(一些可迭代对象知道它们的 length
而无需实际迭代),但这始终是一种风险。在这些情况下,如果副作用是您唯一想要的,请使用 forEach
,或者立即执行 toList
以强制执行所有操作,然后只查看之后的结果列表。
这个forEach
工作得很好
var newMarkers = new List<Marker>();
providers.forEach((p) {
var marker = markerFrom(p);
newMarkers.add(marker);
print("got one");
});
_markers = newMarkers;
但是这个 map
与 forEach
放在完全相同的位置时永远不会被调用:
_markers = providers.map((p) => markerFrom(p));
此外,这是 markerFrom
方法:
Marker markerFrom(FoodProvider provider) {
var marker = new Marker(new MarkerOptions()
..map = _map
..position = new LatLng(provider.latitude, provider.longitude)
..title = provider.name
..icon = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png'
);
var infoWindow = new InfoWindow(new InfoWindowOptions()..content = marker.title);
marker.onClick.listen((e) {
infoWindow.open(_map, marker);
});
return marker;
}
Iterable
上的 map
函数是 lazy。它只是围绕原始 Iterable
创建了一个包装器,但在您开始迭代之前它实际上并没有做任何事情。
这是一件好事,即使如果您习惯了来自其他语言的热切map
功能,这可能会让您感到惊讶。这意味着您可以组合对可迭代对象的操作,例如:
listOfStrings
.map((x) => complicatedOperationOnString(x))
.take(2)
.forEach(print);
这只对前两个字符串进行了复杂的操作。
如果你想要一个标记列表,你需要在 map
:
toList
_markers = providers.map(markerFrom).toList();
一般来说,当传递给 map
的函数具有您希望只发生一次的副作用时,您应该非常小心。如果你多次重复 map
的结果,每次都会发生这种效果,所以如果你这样做:
_markers = providers.map(markerFrom);
int count = _markers.length;
_markers.forEach((marker) { doSomething(marker); });
你会 冒 副作用发生两次的风险,一次是 length
,一次是 forEach
,两者都会重复 _markers
。
它并不总是发生(一些可迭代对象知道它们的 length
而无需实际迭代),但这始终是一种风险。在这些情况下,如果副作用是您唯一想要的,请使用 forEach
,或者立即执行 toList
以强制执行所有操作,然后只查看之后的结果列表。