Array#each 与 Array#map

Posted

技术标签:

【中文标题】Array#each 与 Array#map【英文标题】:Array#each vs. Array#map 【发布时间】:2011-07-12 08:47:41 【问题描述】:
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

这里发生了什么?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

完美的答案可以理解。只是一个.. 免责声明:如果您过度使用 map 函数的返回值,您可能会浪费大量内存。【参考方案3】:

side effects 相同,这给您的逆向工程增加了一些混乱。

是的,两者都对数组进行迭代(实际上,对任何与Enumerable 混合的东西都进行了迭代),但map 将返回一个由块结果组成的数组,而each 将只返回原始数组。

each 的返回值只是原始数组,在 Ruby 代码中很少使用,但map 是most 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, ...]

顺便说一句,您可能很难找到文档,因为 mapEnumerable 中的一种方法,而 each (需要的一种方法Enumerable 模块)是 Array 中的一个方法。

作为一个琐事说明:map 实现基于 each

【讨论】:

【参考方案4】:

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

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

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

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

【讨论】:

【参考方案5】:

这里快速演示地图与每个地图的不同之处

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"] 而每个只是迭代但返回原始数组:["a", "b", "c"]

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

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

您也可以使用 map 和 bang map! 来更改源数组

【讨论】:

这不是问题的答案。问题是关于each 之间的区别,它执行给定的块并返回原始数组;和map,它返回一个数组,其中执行块的结果作为值

以上是关于Array#each 与 Array#map的主要内容,如果未能解决你的问题,请参考以下文章

jQuery.each 实现不同于原生 Array.forEach

JavaScript Array.each函数

Ruby if else 在 array.each

Array each方法 遍历多维数组

Laravel:array_push 在 collection->each() 迭代器中不起作用

使用'Each'方法在do循环中创建新数组