如何理解Ruby的.each和.map
我无法理解map
与each
map
之间的差异,以及何时何地使用它们。
我读过“ 地图做什么? ”和“ Ruby Iterators ”但是想要一些澄清。
如果我有:
z = [1,2,3].map {|x| x + 1}
map
获取数组z
中的每个元素并为每个元素添加一个元素,但是除非我添加,否则它不会改变原始数组!
。
另一方面:
y = [1,2,3].each {|x| x + 1}
返回[1,2,3]
。 这对我来说很困惑,因为:
names = ['danil', 'edmund'] names.each { |name| puts name + ' is a programmer' }
收益:
Danil is a programmer Edmund is a programmer
我的第二个例子中究竟发生了什么,不允许每个数组元素增加1
,而在最后一个例子中,一个字符串被附加到数组中的所有内容?
所有的学分都归Speransky Danil所有,我把这些例子都拿走了。
map
方法在给定一些块的情况下采用enum
,并在执行某些逻辑时迭代它。 在您的情况下,逻辑是x+1
。 正如你所说,除非你使用它,否则不会改变任何东西!
。
each
都只是返回被调用的数组。
我们举一个例子:
names = ["bob"]
如果我们这样做:
names.each{|names| names + "somestring"}
输出仍然是["bob"]
。 你的第二个例子不同的原因是puts
。
作为练习尝试做:
y = [1,2,3].each {|x| puts x + 1}
你会得到:
2 3 4 [1,2,3]
tl; dr:如果我想改变我的collections,对它进行转换,最后得到不同的东西,我会使用map
。 如果我只需要访问集合中的每个元素,我就会使用each
。
关键点是:如果要在数组上应用转换(实际上是可枚举的,但是让我们在开始时保持简单),你应该使用map
。 否则,如果您不需要更改arrays,则只需使用each
arrays即可。
请注意,在下面的代码中,您不会改变数组,但您只是利用本地字符串来打印带有后缀的每个字符串。
names = ['danil', 'edmund'] names.each { |name| puts name + ' is a programmer' }
显然,你可以对map
做同样的事情,但在这种情况下你不需要它,你也必须使用它们来打印每个元素。 代码将是
names = ['danil', 'edmund'] names.map! { |name| name + ' is a programmer' } # or names = names.map { |name| name + ' is a programmer' } name.each { |name| puts name }
Ruby的文档在多个地方都有这个内容,但最容易理解的是在each
的Array文档中:
each { |item| block } → ary each → Enumerator
为self中的每个元素调用给定块一次,将该元素作为参数传递。 返回数组本身。
如果没有给出块,则返回枚举器。
a = [ "a", "b", "c" ] a.each {|x| print x, " -- " }
生产:
a -- b -- c --
请注意,它会显示“ 返回数组本身”。
将其与map
进行比较:
map { |item| block } → new_ary map → Enumerator
为self的每个元素调用给定的块一次。
创建一个包含块返回的值的新数组。
另请参见Enumerable#collect。
如果没有给出块,则返回枚举器。
a = [ "a", "b", "c", "d" ] a.collect { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"] a.map.with_index { |x, i| x * i } #=> ["", "b", "cc", "ddd"] a #=> ["a", "b", "c", "d"]
请注意,它会显示“ 创建一个包含块返回的值的新数组 ”。
这个例子应该有助于了解上述内容:
foo = [1,2,3] foo.each { |i| puts i + 1 } # => [1, 2, 3] foo.map { |i| i + 1 } # => [2, 3, 4] # >> 2 # >> 3 # >> 4
其中# =>
是块的返回值, # >>
是从puts
捕获的STDOUT。
并且,了解所有这些,当您想要在数组中显示元素时,使用each
元素,或者提取并重用这些元素作为参数或构建事物。 如果要将数组的元素更改为其他元素,请使用map
。
不同之处在于each
元素都对数组中的每个元素执行一个操作,返回原始数组。 执行的操作可能会使元素发生变异。
而map
正在对数组中的每个元素执行操作,并将其结果作为数组返回。
在第一种情况下, map
:
z = [1,2,3].map {|x| x + 1}
将获取给定数组中的每个元素并在块中执行操作并返回一个新数组,因此它返回[2,3,4]
。
.each
为数组中的每个元素执行块,它不会更改数组中的任何内容,因此它执行x + 1
,但它不会将它存储在任何地方,因此在第二种情况下它只返回arrays。
现在,在您发布的第三个示例中,您将在块本身中打印输出。 同样,arrays本身没有变化。