如何理解Ruby的.each和.map

我无法理解mapeach 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,则只需使用eacharrays即可。

请注意,在下面的代码中,您不会改变数组,但您只是利用本地字符串来打印带有后缀的每个字符串。

 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本身没有变化。