each_with_object应该如何工作?

Ora*_*bîg 30 ruby

对ruby来说,我正在试图找出each_with_object应该如何使用.

我试着用它来做一个非常简单的总和,所以我写道:

> (1..3).each_with_object(0) {|i,sum| sum+=i}
=> 0
Run Code Online (Sandbox Code Playgroud)

嘿,我认为结果将是6!我的错误在哪里?

tih*_*hom 55

each_with_object 不适用于整数等不可变对象.

(1..3).each_with_object(0) {|i,sum| sum += i} #=> 0
Run Code Online (Sandbox Code Playgroud)

这是因为each_with_object遍历集合,将每个元素和给定对象传递给块.它不会在每次迭代后更新对象的值并返回原始给定对象.

它可以使用哈希,因为更改哈希键的值会自动更改原始对象的值.

(1..3).each_with_object({:sum => 0}) {|i,hsh| hsh[:sum] += i}
#=> {:sum => 6}
Run Code Online (Sandbox Code Playgroud)

String对象很有趣.它们是可变的,所以你可能希望以下内容返回"abc"

("a".."c").each_with_object("") {|i,str| str += i} # => ""
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.这是因为str += "a"返回一个新对象并且原始对象保持不变.但是如果我们这样做

("a".."c").each_with_object("") {|i,str| str << i} # => "abc"
Run Code Online (Sandbox Code Playgroud)

它的工作原理是因为str << "a"修改了原始对象.

有关更多信息,请参阅每个对象的 ruby文档

为了您的目的,使用注入

(1..3).inject(0) {|sum,i| sum += i} #=> 6
# or
(1..3).inject(:+) #=> 6
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案,这些示例应该添加到ruby文档中! (2认同)

spi*_*ann 11

一个简单但常见的例子each_with_object是当你需要根据数组中的元素构建一个哈希时.通常你会看到类似的东西:

hash = {}
[1, 2, 3, 4].each { |number| hash[number] = number**2 }
hash
Run Code Online (Sandbox Code Playgroud)

使用each_with_object避免显式初始化和返回hash变量.

[1,2,3,4].each_with_object({}) { |number, hash| hash[number] = number**2 }
Run Code Online (Sandbox Code Playgroud)

我建议阅读文档inject,tapeach_with_index.当您瞄准简短且可读的代码时,这些方法很有用.


Aru*_*hit 10

文档Enumerable#each_with_object很清楚:

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

在你的情况下,(1..3).each_with_object(0) {|i,sum| sum+=i}你正在传递0,这是不可变对象.因此,这里each_with_object方法的初始对象是0,所以方法返回.0它在广告中工作.看下面的each_with_object工作原理,

(1..3).each_with_object(0) do |e,mem|
    p "#{mem} and #{e} before change"
    mem = mem + e
    p mem
end

# >> "0 and 1 before change"
# >> 1
# >> "0 and 2 before change"
# >> 2
# >> "0 and 3 before change"
# >> 3
Run Code Online (Sandbox Code Playgroud)

这意味着在每次传递中,mem都设置为初始传递的对象.你可能会想到在第一遍mem0,然后在下一遍mem是结果mem+=e,mem即将1.But NO,在每一遍中mem都是你的初始对象,即0.