Ruby 中 [1,2,3].to_enum 和 [1,2,3].enum_for 的区别

Posted

技术标签:

【中文标题】Ruby 中 [1,2,3].to_enum 和 [1,2,3].enum_for 的区别【英文标题】:Differences between [1,2,3].to_enum and [1,2,3].enum_for in Ruby 【发布时间】:2014-07-14 01:32:40 【问题描述】:

在 Ruby 中,我试图了解 to_enumenum_for 方法之间的关系。在我提出问题之前,我已经提供了一些示例代码和两个示例来帮助了解上下文。

示例代码:

# replicates group_by method on Array class
class Array
  def group_by2(&input_block)
    return self.enum_for(:group_by2) unless block_given?
    hash  = Hash.new |h, k| h[k] = [] 
    self.each  |e| hash[ input_block.call(e) ] << e 
    hash
  end
end

示例#1:

irb (main)> puts [1,2,3].group_by2.inspect
=> #<Enumerator: [1, 2, 3]:group_by2> 

在示例 #1 中:在数组 [1,2,3] 上调用 group_by,而不传入块,返回使用命令 self.enum_for(:group_by_2) 生成的枚举器。

示例 #2

irb (main)> puts [1,2,3].to_enum.inspect
=> #<Enumerator: [1, 2, 3]:each> 

在示例 #2 中,枚举数是通过在数组 [1,2,3] 上调用 to_enum 方法生成的

问题:

在示例 1 和 2 中生成的枚举器是否以任何方式表现不同?我可以从检查的输出中看到它们显示的标签略有不同,但我可以发现枚举器的行为有任何差异。

# Output for example #1
#<Enumerator: [1, 2, 3]:each> # label reads ":each"

# Output for example #2
#<Enumerator: [1, 2, 3]:group_by2> # label reads ":group_by2"

【问题讨论】:

【参考方案1】:
p [1, 2, 3].to_enum
p [1, 2, 3].enum_for

--output:--

#<Enumerator: [1, 2, 3]:each>
#<Enumerator: [1, 2, 3]:each>

来自文档:

to_enum

创建一个新的枚举器,它将通过调用方法来枚举 obj,如果有的话,传递 args。

...

enum_for

创建一个新的枚举器,它将通过调用方法来枚举 obj,如果有的话,传递 args。

ruby 是一种语言,其方法名称通常是同义词。

后续问题:

命令 [1,2,3].to_enum(:foo) 中的符号是否有作用, 除了在输出中用 :foo 替换 :each 吗?

是的。默认情况下,ruby 将枚举器连接到接收器的 each() 方法。有些类没有each() 方法,例如String:

str = "hello\world"
e = str.to_enum
puts e.next

--output:--
1.rb:3:in `next': undefined method `each' for "helloworld":String (NoMethodError)
    from 1.rb:3:in `<main>

to_enum() 允许您指定希望枚举器使用的方法:

str = "hello\nworld"
e = str.to_enum(:each_line)
puts e.next

--output:--
hello

现在,假设您有数组[1, 2, 3],并且您想为您的数组创建一个枚举器。数组有一个 each() 方法,但不是用 each() 创建一个枚举器,它将返回数组中的每个元素,然后结束;你想创建一个枚举器,一旦到达数组的末尾就从数组的开头重新开始?

e = [1, 2, 3].to_enum(:cycle)

10.times do
  puts e.next()
end

--output:--
1
2
3
1
2
3
1
2
3
1

【讨论】:

@ 7stud 谢谢。只是想确保我没有遗漏什么。 @amorphid, ruby​​ 文档曾经很擅长说,“这个方法是方法 A 的同义词。参见方法 A 的描述。”我宁愿看到那个推荐而不是重复的描述。 我刚刚重读了您的示例,刚刚意识到也可以执行[1,2,3].to_enum(:foo),它返回#&lt;Enumerator: [1, 2, 3]:foo&gt;。如果我意识到这一点,我的问题只是 => 命令[1,2,3].to_enum(:foo) 中的符号是否有目的,而不是在输出中用:foo 替换:each? docs for the Enumerator class 对此只字不提,至少我看不到。 @amorphid,我编辑了我的帖子来回答你的后续问题。 谢谢。这正是我一直在寻找的答案!我花了一点时间才弄清楚如何提出这个问题:)

以上是关于Ruby 中 [1,2,3].to_enum 和 [1,2,3].enum_for 的区别的主要内容,如果未能解决你的问题,请参考以下文章

to_enum(:method) 如何在这里接收它的块?

ruby-2.4.6和redis-4.1.3.gem环境下的redis-cluster集群中的bug

推荐用于 Rails 3.1 和 Ruby 1.9.2 的开发 Web 服务器

了解范围和数组中的 ruby​​ splat

如何在 Ruby 中随机排序(打乱)数组?

ruby - uniq 有啥区别!和 uniq [重复]