枚举#with_object与enum#each_with_object的不同之处是什么?

时间:2013-02-03 11:18:15

标签: ruby ruby-1.9

文档说:

  

enum#each_with_object :-

     

使用任意对象obj迭代每个元素的给定块,并返回obj

  

enum#with_object:-

     

使用任意对象obj迭代每个元素的给定块,并返回obj

但是当我在这两个结构上尝试下面的内容时,一个按预期给了我输出但是其他没有。所以我怀疑这两种结构之间存在差异。

使用each_with_object

%w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase }
=> {"foo"=>"FOO", "bar"=>"BAR"}

在这里取得成功!

使用with_object

%w(foo bar).with_object({}) { |str, hsh| hsh[str] = str.upcase }
 => NoMethodError: undefined method `with_object' for ["foo", "bar"]:Array
    from (irb):1
    from C:/Ruby193/bin/irb:12:in `<main>'

在这里失败了!

那么这两种方法有什么区别?

2 个答案:

答案 0 :(得分:5)

with object仅适用于枚举器,这意味着您必须将其链接到返回枚举器的内容。例如

%w(foo bar).each.with_object({}) { |str, h| h[str] = str.upcase }

%w(foo bar).detect.with_object(obj) { ... }

因此,如果你没有给它一个块(例如with_objectmapreduce,{detect,那么你可以在任何返回枚举器的地方调用find_all {1}} ...)。这包括Enumerable中混合的任何内容。

each_with_object基本上是each.with_object的别名。

答案 1 :(得分:5)

each返回一个Enumerator对象。

%w(foo bar).each.class
=> Enumerator

因此,对于第一种情况,数组首先转换为Enumerator,然后在with_object上运行。

如果您希望第二种情况有效,则必须将数组转换为Enumerator。您可以使用.to_enum.each.map转换数组。

%w(foo bar).map.with_object({}) { |str, hsh| hsh[str] = str.upcase }
=> {"foo"=>"FOO", "bar"=>"BAR"}

更多详情:Enumerator