我正在计算项目在枚举中出现的次数.
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
Run Code Online (Sandbox Code Playgroud)
reduce方法似乎应该与find_all方法具有相同的行为.为什么它会返回nil而不是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>'
Run Code Online (Sandbox Code Playgroud)
在第一次迭代中出现了问题.可以减少不使用这种方式吗?
在reduce中,块中代码的值被分配给累加器.在你的情况下,你覆盖第一个赋值与后来的nils相加.
你可以解决这个问题:
(1..3).reduce(0) {|sum, p| sum += 1 if p == 1; sum}
Run Code Online (Sandbox Code Playgroud)
要么
(1..3).reduce(0) {|sum, p| sum += p == 1 ? 1 : 0}
Run Code Online (Sandbox Code Playgroud)
对于您的第二个示例,在第一次迭代时将sum指定为nil,并且您尝试在第二次迭代中将n添加1.
请记住,减少/注入可能不是计数的最佳工具 - 试试
(1..3).count(1)
Run Code Online (Sandbox Code Playgroud)
从给予所述块中的返回值(或最后一个值)Enumerable#reduce方法被始终存储为在每次呼叫累加器的新的值,所以递增就地(总和sum+=1)是误导性的.您块返回预期值,如果p==1而是nil否则,这样的蓄电池被覆盖.
尝试修改您的块以始终返回累加器的预期值(总和),例如:
(1..3).reduce(0) { |sum,p| (p==1) ? sum+1 : sum }
Run Code Online (Sandbox Code Playgroud)
reduce方法实现中的调用序列如下所示:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
894 次 |
| 最近记录: |