Почему инъекция рубина не суммируется правильно?
Я не получаю правильные результаты от следующего метода исправления обезьян в Integer:
def harm
1 + (2..self).inject{|sum, x| sum + 1/x.to_r}
end
2.harm #=> 3
вместо этого он должен вернуть 3/2, где моя ошибка?
3 ответа
Здесь есть две проблемы:
Когда вы перебираете закрытый диапазон, такой как
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}
Standalone:
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)
Документация Enumerable#inject
:
Если вы указываете блок, то для каждого элемента в перечислении блоку передается значение аккумулятора (памятка) и элемент. Если вместо этого указать символ, то каждый элемент в коллекции будет передан в именованный метод memo. В любом случае результат становится новым значением для памятки. В конце итерации конечное значение 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)
Тем не менее, обратите внимание, что для большого числа этот хорошо читаемый код становится неэффективным, так как он подготавливает массив в памяти перед выполнением суммирования.