2

我没有从 Integer 中的以下猴子修补方法得到正确的结果:

def harm
  1 + (2..self).inject{|sum, x| sum + 1/x.to_r}
end

2.harm #=> 3

它应该返回 3/2,我的错误在哪里?

4

3 回答 3

4

这里有两个问题:

  1. 当您遍历一个封闭范围时,例如2..2,实际上什么都没有发生:

    (0..0).inject(){|s, x| s+= 99 }
    # => 0
    

    这就是为什么你得到3,因为1 + 23

  2. 如果您不将参数传递给inject,它将使用您传递给迭代器的第一个值作为起始备忘录,即2

    (2..2).inject(){|s, x| s+= 99 }
    #=> 2
    

    输入 0 可以获得实际的迭代:

    (2..2).inject(0){|s, x| s+= 99 }
    #=> 99
    

所以在你的方法中试试这个:

1 + (2..self).inject(0){|sum, x| sum + 1/x.to_r}  

独立:

1 + (2..2).inject(0){|sum, x| sum + 1/x.to_r}  
#=> 3/2
于 2013-10-13T14:04:42.383 回答
2

这是提示(您需要将初始值传递给inject方法):

def harm
  1 + (2..2).inject(0){|sum, x| sum + 1/x.to_r}
end

harm # => (3/2)

文档Enumerable#inject

如果您指定一个块,那么对于枚举中的每个元素,该块都会传递一个累加器值(备忘录)和元素。如果你指定了一个符号,那么集合中的每个元素都将被传递给 memo 的命名方法。无论哪种情况,结果都会成为 memo 的新值。在迭代结束时,memo 的最终值就是方法的返回值。

如果没有显式指定 memo 的初始值,则 collection 的第一个元素用作 memo 的初始值。

于 2013-10-13T14:00:21.443 回答
1

在我决定花 1 分钟解决您的问题的时间里,我无法意识到您的代码有什么问题。但是我能够编写这个方法来做类似于你想做的事情:

class Integer
  def harm
    return 0 if self == 0
    return -(-self).harm if self < 0
    ( 1 .. self ).map { |n| Rational 1, n }.reduce :+
  end
end

0.harm #=> 0
2.harm #=> 3/2
7.harm #=> 363/140
-2.harm #=> (-3/2)

但是请注意,对于大量数据,这种高度可读的代码变得低效,因为它在执行求和之前在内存中准备了数组。

于 2013-10-14T00:15:53.867 回答