以下代码工作:
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是奇数的?
这里可以使用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
每个回合x
始终是每次通过的"对象"并最终返回。
更容易:
(0..10).select(&:odd?)
在哪里过滤以获取所有奇数,无需传递临时数组。
reduce
的每次迭代都应返回某些东西。在您当前的代码中,当y
不奇怪时,reduce
循环的迭代返回nil
,因此在下一个迭代中,x
等于nil
,它没有方法push
,因此NoMethodError
。
如果y
不奇怪,可以通过返回x
来处理此操作,例如:
(0..10).to_a.reduce([]) { |x, y| y.odd? ? x.push(y) : x }
与结果:
[1, 3, 5, 7, 9]