为什么Ruby只在我使用'if'条件时抱怨"未定义的方法`+'为nil:NilClass(NoMethodError)"

TCS*_*rad 5 ruby debugging

我正在Ruby 中的项目Euler中尝试问题6(在我尝试学习语言时),这是我在第一次迭代中提出的:

upto = 10
a = (1..upto).to_a.product((1..upto).to_a)
#a.each{ |x| print "(#{x[0]}, #{x[1]})\n"}
puts a.inject(0) {|sum, x| sum + x[0]*x[1] if (x[0] != x[1])}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这会在Ruby 2.0上引发以下错误:

in block in <main>': undefined method+'for nil:NilClass(NoMethodError)

更令人费解的是,当我删除if条件时没有遇到错误(这显然给了我错误的答案顺便说一句!)

upto = 10
a = (1..upto).to_a.product((1..upto).to_a)
a.each{ |x| print "(#{x[0]}, #{x[1]})\n"}
puts a.inject(0) {|sum, x| sum + x[0]*x[1]} #if (x[0] != x[1])}
Run Code Online (Sandbox Code Playgroud)

上面给出了以下输出(在打印出a的元素之后):

3025

作为一个调试步骤,我甚至打印出'a'的内容,以确保没有零元素 - 结果很好.有人可以解释一下

  1. 我在这里做错了什么?
  2. 当我省略'if'条件时,为什么差异,因为错误信息在'+'运算符中,否则无条件执行?

编辑:对于获得相同,更优雅的方法来获得相同解决方案的评论也是很好的,因为我想知道Rubyist解决这个问题的标准方法!

Fre*_*ung 2

我确信您知道, 的值sum是块在前一个表达式上求值的值(或第一次提供的初始值)

你的代码应该做的是

if x[0] != x[1]
  sum + x[0]*x[1]
else
  sum
end
Run Code Online (Sandbox Code Playgroud)

您的代码有效地忽略了 else,因此当不满足条件时,您的块评估为 0

您可能还想知道

(1..upto).combination(2).to_a
Run Code Online (Sandbox Code Playgroud)

直接为您提供非重复对的数组,这样您就不需要在注入中使用 if 语句

你甚至可以这样做

(1..upto).to_a.combination(2).collect {|pair| 2* pair[0] * pair[1]}.inject(:+)
Run Code Online (Sandbox Code Playgroud)