Array#each vs. Array #map

时间:2011-03-10 00:34:47

标签: ruby arrays enumerable

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

这里发生了什么?

7 个答案:

答案 0 :(得分:167)

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"]

答案 1 :(得分:32)

side effects是相同的,这给你的逆向工程增加了一些困惑。

是的,两者都遍历数组(实际上,在Enumerable中混合的任何内容),但map将返回由块结果组成的数组,而each将返回原始数据阵列。

each的返回值只是原始数组,在Ruby代码中很少使用,但mapmost important functional tools之一。

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 中的方法,而每个(需要一种方法)通过 Enumerable 模块)是 Array 中的方法。

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

答案 2 :(得分:13)

以下是地图与每个

的不同之处的快速演示
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_a", "map_b", "map_c"],而每个地图只会迭代但返回原始数组:["a", "b", "c"]

因此,每个都用于处理数组,而map用于处理已处理的数组。

答案 3 :(得分:4)

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

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

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

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

答案 4 :(得分:0)

当你使用map到hash时,它会隐式地将哈希值转换为数组,所以你有

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

vs.each {...}只返回最后一次评估,[“d”,[11,22]]和[33,44,55]为[“f] [11,22] “,[33,44,55]]。所以在最后一次加入之前,你有

[[11, 22], [33, 44, 55]]

答案 5 :(得分:0)

Array#每个方法返回相同的数组

IF NOT EXISTS (SELECT * FROM EMPLOYEE WHERE Name = 'BOB')

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

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

答案 6 :(得分:0)

您还可以将map与爆炸map!配合使用,以更改源数组