map和each的区别

28

除了Andrew和Bryan的答案之外,我要补充一下还有另一种方法叫做collect,它与map完全相同 ;) - Aldo 'xoen' Giambelluca
是的,mapcollect是等价的。虽然我从来没有喜欢过"collect"这个名字,因为我认为它并不能很好地描述它的功能。 - Andrew Marshall
2个回答

76

each 简单地遍历给定的可枚举对象,对每个值运行块。它会丢弃块的返回值,并简单地返回调用它的原始对象:

[1, 2, 3].each do |x|
  x + 1
end  # => [1, 2, 3]

这只是一种更简洁、更通用的方式来实现传统的迭代 for 循环,而在 Ruby 中,each 要比 for 循环更受欢迎(实际上,我想我从未在 Ruby 中使用过 for 循环)。

map函数会遍历每个元素,使用块的返回值在每个对应的索引处填充一个新数组,并返回该新数组:

[1, 2, 3].map do |x|
  x + 1
end  # => [2, 3, 4]

因此,它使用给定的块将每个元素“映射”到一个新元素,因此被称为“map”。请注意,eachmap本身都不会修改原始集合。这是在迭代循环中创建数组并将其推入其中的简洁的函数式替代方法。

5
值得强调的是,它不会在原始集合中设定任何值,仅在返回的副本中设定。 - SasQ
“将当前正在迭代的元素设置为返回值”听起来像是正在被块的值替换当前元素。而“with those changes”强调有些东西正在发生改变。这将是Array#map!(带有bang)的一个好的解释。另一方面,map(包括Enumerable#mapArray#map)都会返回一个新数组(无论给定接收器如何),其中包含通过块返回的值,而不会更改接收器。 - Stefan
1
@Stefan 我能理解你的困惑,希望这次更新能够澄清一些事情(这篇文章写于很久以前!)。 - Andrew Marshall

8

each 返回原始对象。它用于在不收集任何结果的情况下使用数组的每个元素运行操作。例如,如果您想打印一个数字列表,可以这样做:

arr = [1, 2, 3, 4]
arr.each { |n| puts n }

现在,上面的puts方法实际上返回的是nil。有些人不知道这一点,但这并不重要;收集那个值没有任何真正的理由(如果你想将arr转换为字符串,你应该使用arr.map(&:to_s)arr.map { |n| n.to_s })。
map返回您传递给它的块的结果。这是一种在数组中对每个元素运行操作并检索结果的好方法。如果您想将数组的每个元素乘以2,这是自然的选择。作为奖励,您可以使用map!修改原始对象。例如:
arr = [1, 2, 3, 4]
arr.map! { |n| n * 2}
# => [2, 4, 6, 8]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接