98
hash = { "d" => [11, 22], "f" => [33, 44, 55] }

# case 1
hash.map {|k,vs| vs.map {|v| "#{k}:#{v}"}}.join(",")
=> "d:11,d:22,f:33,f:44,f:55"

# case 2
hash.map {|k,vs| vs.each {|v| "#{k}:#{v}"}}.join(",")
=> "11,22,33,44,55"

唯一的区别是案例 1 使用vs.map,案例 2 使用vs.each

这里发生了什么?

4

7 回答 7

188

Array#each为数组的每个元素执行给定的块,然后返回数组本身。

Array#map还为数组的每个元素执行给定的块,但返回一个新数组,其值是块的每次迭代的返回值。

示例:假设您有一个这样定义的数组:

arr = ["tokyo", "london", "rio"]

然后尝试执行each

arr.each { |element| element.capitalize }
# => ["tokyo", "london", "rio"]

请注意,返回值只是相同的数组。块内的代码each被执行,但不返回计算值;并且由于代码没有副作用,因此这个示例没有执行任何有用的工作。

相反,调用数组的map方法会返回一个新数组,其元素是每轮执行map块的返回值:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
于 2011-03-10T00:42:39.000 回答
35

副作用_是相同的,这给您的逆向工程增加了一些混乱

是的,两者都遍历数组(实际上,遍历Enumerable中混合的任何内容),但是map将返回一个由块结果组成的数组,而每个都只会返回原始数组。

each的返回值只是原始数组,在 Ruby 代码中很少使用,但map最重要的功能工具之一之一。

什么map是返回一个数组,其中包含传递的块或命名方法的结果。例如:

    2.2.3 :001 > [:how, :now, :brown, :cow].map &:to_s
 => ["how", "now", "brown", "cow"]

在这种情况下,我没有传递一个块,而只是传递了一个Symbol,但是class Symbol对象有一个to_proc方法,它将导致:

[:how.to_s, :now.to_s, ...]

顺便说一句,您可能很难找到文档,因为map是 Enumerable 中的一种方法,each Enumerable 模块所需的一种方法Array中的一种方法。

作为一个琐事说明:地图实现基于每个.

于 2011-04-19T16:02:45.087 回答
14

这是地图如何与每个地图不同的快速演示

a = ["a", "b", "c"];
#Array.map
p a.map {|item| "map_" + item}
#prints ["map_a", "map_b", "map_c"]

#Array.each
p a.each {|item| "map_" + item}
#prints ["a", "b", "c"]

您会看到 map 返回["map_a", "map_b", "map_c"],而 each 只是迭代但返回原始数组:["a", "b", "c"]

因此 each 用于处理数组,而 map 用于处理处理过的数组。

于 2014-05-19T16:41:55.247 回答
4

.each返回您最初提供的相同数组:

[1,2,3].each { |i| i + 1 }
#=> [1,2,3]

.map从每个块调用的结果中返回一个新数组:

[1,2,3].map { |i| i + 1 }
#=> [2,3,4]
于 2014-04-23T18:37:01.253 回答
1

Array#each 方法返回相同的数组

a = [1,2,3,4,5]
a.object_id #70284994490700

b = a.each {|n| n + 2}
p b #[1,2,3,4,5]
b.object_id #70284994490700 <<--- it's the same as a

Array#map 方法返回一个新数组

c = [1,2,3,4,5]
c.object_id #70219117705860

d = c.map {|n| n + 2}
p d #[3,4,5,6,7]
d.object_id #70284994343620  <<---- it's different than c
于 2017-11-02T18:07:21.287 回答
0

当您使用映射到哈希时,它会隐式地将哈希转换为数组,因此您有

[["d", [11, 22]], ["f", [33, 44, 55]]]

vs.each{...} 只给你最后一次评估,即 [11, 22] for ["d", [11, 22]] 和 [33, 44, 55] for ["f", [ 33、44、55]]。所以在最后一次加入之前,你有

[[11, 22], [33, 44, 55]]
于 2011-03-10T00:42:37.210 回答
0

你也可以使用mapwith bangmap!来改变源数组

于 2020-03-26T16:07:15.900 回答