Почему за редукцией ([]) вызывается ошибка NoMethodError, когда он пытается передать значение - PullRequest
0 голосов
/ 01 марта 2019

Работает следующий код:

irb(main):001:0> (0..10).to_a.reduce([]) { |x, y| x.push(y) }
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Но это вызывает NoMethodError:

irb(main):002:0> (0..10).to_a.reduce([]) { |x, y| x.push(y) if y.odd? }
Traceback (most recent call last):
        5: from /root/.irb:280:in `<main>'
        4: from (irb):2
        3: from (irb):2:in `reduce'
        2: from (irb):2:in `each'
        1: from (irb):2:in `block in irb_binding'
NoMethodError (undefined method `push' for nil:NilClass)

Почему это так?Не следует ли позднее перенести переменную y в массив x, если y нечетно?

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Здесь можно использовать reduce, но вы должны правильно соединиться.Возвращаемое значение каждой итерации отправляется в следующее:

(0..10).reduce([ ]) do |x, y|
   x << y if (y.odd?)
   x
end

Поскольку эта цепочка может раздражать, поскольку вещь, которую вы цепляете, никогда не меняется, есть альтернатива:

(0..10).each_with_object([ ]) do |y, x|
   x << y if (y.odd?)
end

Где каждыйround x - это всегда "объект", который передается каждый раз и в конечном итоге возвращается.

Еще проще:

(0..10).select(&:odd?)

Где это просто фильтрует, чтобы захватить все нечетные значения, нет необходимостиобойти временный массив.

0 голосов
/ 01 марта 2019

Каждая итерация reduce должна что-то возвращать.В вашем текущем коде, когда y не является нечетным, эта итерация цикла reduce возвращает nil, поэтому на следующей итерации x равен nil, который не имеет метода pushследовательно, NoMethodError.

Вы можете справиться с этим, возвращая x без изменений, если y не является нечетным, например так:

(0..10).to_a.reduce([]) { |x, y| y.odd? ? x.push(y) : x }

С результатом:

[1, 3, 5, 7, 9]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...