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, ...]
顺便说一句,您可能很难找到文档,因为 map 是 Enumerable 中的一种方法,而 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