如何理解#map方法的核心概念

时间:2015-02-16 07:14:47

标签: ruby-on-rails ruby

我读了这篇文章about enumerable-enumeratormapEnumerable

的方法
module Enumerable
    def map(*several_variants) ## `*several_variants`  [https://stackoverflow.com/questions/28527931/definition-of-ruby-inbuilt-methods][2]
        #This is a stub, used for indexing
    end
end

class Enumerator  # Enumerator class has included Enumerable module Ok fine !!!
    include Enumerable # many  thing are there ...    
end

Array课程中:

 class Array # Array class has included Enumerable module it means all the instances methods of  Enumerable module will expose as the instance methods in  Array class !!! Okk
     include Enumerable  # many  thing are there ...
 end

现在,当我在数组上调用map方法时,我得到Enumerator

[1,2,3,4].map   => #<Enumerator: [1, 2, 3, 4]:map> 

1:上面Enumerator输出行中的#<Enumerator: [1, 2, 3, 4]:map>是什么?

 module Test

  def initialize(str)
    @str = str
  end

  def methods_1(str)
    p "Hello!!#{str}"
  end
 end

 class MyTest
  include Test
  include Enumerable
 end

 my_test = MyTest.new('Ruby')
 p  "Which class ? : #{my_test}"
 my_test.methods_1('Rails')
 p my_test.map

输出

"Which class ? : #<MyTest:0x000000019e6e38>"
"Hello!!Rails"
#<Enumerator: #<MyTest:0x000000019e6e38 @str="Ruby">:map> 

2:只有在我没有错的情况下,这应该是 MyTest类的对象

3:在这一行#<Enumerator: #<MyTest:0x000000019e6e38 @str="Ruby">:map>中,Enumerator做了什么?

感谢所有人在短时间内明确这个概念。 我想分享一些有用的链接,以便在很大程度上掌握这个概念。

Map, Select, and Other Enumerable Methods

What does the “map” method do in Ruby?

Enumerable and Enumerator

Ruby tricks to make your code more fun and less readable

3 个答案:

答案 0 :(得分:1)

我认为你的问题不是Enumerable#map特有的。如果您浏览Enumerable模块,您将找到许多方法(包括map),如果给出一个块则返回一个,如果没有给出块,则返回一个枚举器。假设你写了,

[1,2,3].map.with_index { |x,idx| x+idx } #=> [1,3,5]

map没有给出一个块,所以它返回一个枚举器:

enum1 = [1,2,3].map
  #=> #<Enumerator: [1, 2, 3]:map>

然后将方法Enumerator#with_index发送到enum1

enum2 = enum1.with_index
  #=> #<Enumerator: #<Enumerator: [1, 2, 3]:map>:with_index>

如您所见,enum2也是一个枚举者,一种&#34;复合枚举器&#34;。

enum2确实有一个块,因此它的元素会通过调用Enumerator#eachArray#each方法传递到块中。

我们可以通过将其转换为数组来查看任何枚举器的内容:

enum2.to_a
  #=> [[1, 0], [2, 1], [3, 2]]

这向我们展示了each将传递到块中的元素,第一个是数组[1, 0],从而导致块变量x被赋值1以及要分配idx的块变量0

计算的最后一步由Array#each执行:

enum2.each { |x,idx| x+idx } #=> [1,3,5]

Enumerator#with_index(以及map和大多数其他Enumerable方法)的文档说,当给出一个块时,它会返回一个对象(通常不是枚举器) ,并在没有给出块时返回枚举器。然而,正如我刚刚展示的那样,它无论如何都会产生一个普查员;当它跟着一个区块时,它会打电话给接收者的班级&#39; <{1}}做法的方法。

是的,您可以在自己的班级中each,但要使用该模块的方法,您还必须为您的班级定义include Enumerable方法。

它的枚举器允许我们链接方法,并有效地执行此操作,而无需在链接之间创建临时数组和其他此类对象。

我曾经给出了以下关于each模块如何形成的奇怪描述:

有一天,很久以前,来自旭日之地的一个非常聪明的Rubyest注意到他用于阵列的许多方法与他用于哈希,范围和其他收藏的方法非常相似。他看到他可以写出来,唯一不同的是方法&#34;每个&#34;实施了,所以他把它们全部放在一个他称之为“#34;可算の&#34; (&#34; Enumerable&#34;),然后在他添加的所有不同类型的集合的类中,包括Enumerable&#34;和方法&#34;每个&#34;。在这之后,他想,&#34;生活は快适です&#34; (&#34;生活很好&#34;)。

答案 1 :(得分:0)

map方法的基本思想是,对于元素的每次迭代,map将块中执行的最后一个表达式的值插入到新数组中。执行完最后一个元素后,map会返回new array个值。

在你的例子中:

  1. Enumerator只是Ruby中的一个类。当您未在[1,2,3,4].map上添加块时,您已对其进行了实例化。请注意,它与Enumerable

  2. 不同
  3. 是的,这是你的 MyTest 课程。如果您想测试它,请执行my_test.class

  4. 您只是通过执行Enumerator来实例化my_test.map对象,并且ruby看到您已经在您的班级中包含了Enumerable模块。

答案 2 :(得分:0)

map最常见的用法是使用一个块,如下所示:

[1, 2, 3, 4].map { |n| n*n }
# => [1, 4, 9, 16]

但是,如果你在没有传递阻止的情况下调用map,它仍会返回一些内容。在这种情况下,它返回一个Enumerator,它知道原始数组,并且它是一个“map”类型的数组。它可以用于链接其他Enumerator方法,例如:

[1, 2, 3, 4].map.with_index { |n, idx| "entry #{idx} squared: #{n*n}" }
# => ["entry 0 squared: 1", "entry 1 squared: 4", "entry 2 squared: 9", "entry 3 squared: 16"]

您可以阅读有关the Enumerator class的更多文档,但在实践中,您可能希望了解如何将map与更多块一起使用。