我没有从 Integer 中的以下猴子修补方法得到正确的结果:
def harm
1 + (2..self).inject{|sum, x| sum + 1/x.to_r}
end
2.harm #=> 3
它应该返回 3/2,我的错误在哪里?
我没有从 Integer 中的以下猴子修补方法得到正确的结果:
def harm
1 + (2..self).inject{|sum, x| sum + 1/x.to_r}
end
2.harm #=> 3
它应该返回 3/2,我的错误在哪里?
这里有两个问题:
当您遍历一个封闭范围时,例如2..2
,实际上什么都没有发生:
(0..0).inject(){|s, x| s+= 99 }
# => 0
这就是为什么你得到3
,因为1 + 2
是3
。
如果您不将参数传递给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
这是提示(您需要将初始值传递给inject
方法):
def harm
1 + (2..2).inject(0){|sum, x| sum + 1/x.to_r}
end
harm # => (3/2)
如果您指定一个块,那么对于枚举中的每个元素,该块都会传递一个累加器值(备忘录)和元素。如果你指定了一个符号,那么集合中的每个元素都将被传递给 memo 的命名方法。无论哪种情况,结果都会成为 memo 的新值。在迭代结束时,memo 的最终值就是方法的返回值。
如果没有显式指定 memo 的初始值,则 collection 的第一个元素用作 memo 的初始值。
在我决定花 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)
但是请注意,对于大量数据,这种高度可读的代码变得低效,因为它在执行求和之前在内存中准备了数组。