如何理解Ruby的.each和.map

时间:2016-08-25 13:03:28

标签: arrays ruby

我无法理解mapeach之间的差异,以及使用它们的位置和时间。

我读了" What does map do?"和" 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所有,我将这些例子摘下来。

5 个答案:

答案 0 :(得分:3)

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]

答案 1 :(得分:3)

tl; dr:如果我想改变我的收藏,对它进行转换,最后得到不同的东西,我会使用map。如果我只需要访问集合中的每个元素,我都会使用each

关键点是:如果要在数组上应用转换(实际上是可枚举的,但是让我们在开始时保持简单),则应使用map。否则,如果您不需要更改阵列,只需使用each

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

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 }

答案 2 :(得分:1)

Ruby的文档涵盖了多个地方,但您最容易理解的是each的数据文档:

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

答案 3 :(得分:0)

在第一种情况下,map

 z = [1,2,3].map {|x| x + 1}

将获取给定数组中的每个元素并在块中执行操作并返回一个新数组,因此它返回[2,3,4]

.each为数组中的每个元素执行块,并且它不会更改数组中的任何内容,因此它执行x + 1,但它不会将其存储在任何位置,因此在第二种情况下,它只返回数组。

现在,在您发布的第三个示例中,您将在块本身中打印输出。同样,阵列本身也没有变化。

答案 4 :(得分:0)

不同之处在于each正在对数组中的每个元素执行操作,返回原始数组。执行的操作可能会使元素发生变异。

map正在对数组中的每个元素执行操作,并将其结果作为数组返回。