Reduce returns nil on summation

拟墨画扇 提交于 2019-12-10 12:18:49

问题


I'm counting the number of times an item appears in an Enumeration.

irb(main):003:0> (1..3).reduce(0) {|sum, p| sum += 1 if p == 1}
=> nil
irb(main):004:0> (1..3).find_all{|p| p == 1}.length
=> 1

The reduce method seems like it should have the same behaviour as the find_all method. Why does it return nil instead of 1?

irb(main):023:0> (1..3).reduce(0) {|sum, p| sum += 1 if p == 2}
NoMethodError: undefined method `+' for nil:NilClass
    from (irb):23:in `block in irb_binding'
    from (irb):23:in `each'
    from (irb):23:in `reduce'
    from (irb):23
    from /usr/bin/irb:12:in `<main>'

Something is going wrong in the first iteration. Can reduce just not be used this way?


回答1:


In reduce, the value of the code in the block is assigned to the accumulator. In your case you override the first assignment to sum with later nils.

You can fix this by:

(1..3).reduce(0) {|sum, p| sum += 1 if p == 1; sum}

or

(1..3).reduce(0) {|sum, p| sum += p == 1 ? 1 : 0}

For your second example, sum is assigned nil on the first iteration, and you are trying to add 1 to nil on the second.

Please keep in mind that reduce/inject is probably not the best instrument for counting - try

(1..3).count(1)



回答2:


The return value (or last value) from the block given to the Enumerable#reduce method is always stored as the new value of the accumulator at each call, so incrementing the sum in-place (sum+=1) is misleading. Your block returns the expected value if p==1 but nil otherwise, so the accumulator gets overwritten.

Try modifying your block to always return the expected value of the accumulator (sum), e.g.:

(1..3).reduce(0) { |sum,p| (p==1) ? sum+1 : sum }

The call sequence in the reduce method implementation will look something like this:

acc = 0
acc = yield(acc, 1) # (sum=0, p=1) => sum+1 => 1
acc = yield(acc, 2) # (sum=1, p=2) => sum => 1
acc = yield(acc, 3) # (sum=1, p=3) => sum => 1
acc # => 1


来源:https://stackoverflow.com/questions/12488579/reduce-returns-nil-on-summation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!