我读了这篇文章about enumerable-enumerator。 map
是Enumerable
:
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
答案 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#each的Array#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
个值。
在你的例子中:
Enumerator
只是Ruby中的一个类。当您未在[1,2,3,4].map
上添加块时,您已对其进行了实例化。请注意,它与Enumerable
是的,这是你的 MyTest 课程。如果您想测试它,请执行my_test.class
您只是通过执行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
与更多块一起使用。