为什么 map 不起作用而 foreach 起作用? [英] Why is map not working but foreach is?

查看:36
本文介绍了为什么 map 不起作用而 foreach 起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个 forEach 工作得很好

var newMarkers = new List<Marker>();
providers.forEach((p) {
  var marker = markerFrom(p);
  newMarkers.add(marker);
  print("got one");
});

_markers = newMarkers;

但是这个 map 在与 forEach 放在完全相同的地方时永远不会被调用:

but this map doesn't ever get called when placed in the exact same place as the 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 周围创建了一个包装器,但在您开始迭代之前它实际上不会做任何事情.

The map function on Iterable is lazy. It just creates a wrapper around the original Iterable, but it doesn't actually do anything until you start iterating.

这是一件好事,即使您已经习惯了其他语言的急切map 函数,这可能会令人惊讶.这意味着您可以在可迭代对象上组合操作,例如:

That's a good thing, even if it can be surprising if you are used to an eager map function from other languages. It means that you can combine operations on iterables like:

listOfStrings
    .map((x) => complicatedOperationOnString(x))
    .take(2)
    .forEach(print);

这里只对前两个字符串做复杂的操作.

This only does the complicated operation on the first two strings.

如果你想要一个标记列表,你需要在map之后调用toList:

If you want a list of the markers, you need to call toList after the map:

_markers = providers.map(markerFrom).toList();

通常,当传递给 map 的函数具有您希望只发生一次的副作用时,您应该非常小心.如果你多次迭代 map 的结果,每次都会发生这种效果,所以如果你这样做了:

In general, you should be very careful when the function passed to map has side-effects that you want to only happen once. If you iterate the result of map more than once, that effect will happen each time, so if you did:

_markers = providers.map(markerFrom);
int count = _markers.length;
_markers.forEach((marker) { doSomething(marker); });

你会冒险副作用发生两次,一次是length,一次是forEach,它们都迭代_markers.它并不总是发生(一些迭代器知道它们的 length 而不实际迭代),但这总是有风险的.在这些情况下,要么使用 forEach 如果副作用是你唯一追求的,要么立即执行 toList 以强制执行所有操作,然后只查看之后的结果列表.

you would risk the side effects happening twice, once for length and once for forEach, which both iterate _markers. It doesn't always happen (some iterables know their length without actually iterating), but it is always a risk. In those cases, either use forEach if the side-effect is the only thing you are after, or do an immediate toList to force all the operations, and then only look at the resulting list after that.

这篇关于为什么 map 不起作用而 foreach 起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆