【问题标题】:Program working, but I'm still getting a NoMethodError 'length' nil程序正常工作,但我仍然得到 NoMethodError 'length' nil
【发布时间】:2018-11-12 15:34:15
【问题描述】:

这个程序接受两个字符串数组,然后从 a2 中的最短者中减去 a1 中最长者的长度,反之亦然,并返回较大者。

它可以工作(通过 103/103 测试),但我收到此错误:

NoMethodError: undefined method `length' for nil:NilClass 
main.rb:10:in `mxdiflg'
main.rb:66:in `block (2 levels) in <main>'

问题出在哪里?而且由于这不是第一次发生这种情况,我该如何调试可以运行的程序?

def mxdiflg(a1, a2)
    if a1 == '' || a2 == ''
    -1
  end
  a1_order = a1.sort{|left, right| left.length <=> right.length}
  a2_order = a2.sort{|left, right| left.length <=> right.length}

  a_total = a1_order.reverse[0].length - a2_order[0].length
  b_total = a2_order.reverse[0].length - a1_order[0].length

  if b_total > a_total
    b_total
  else
    a_total
  end
end

【问题讨论】:

  • 如果此方法采用“两个字符串数组”,那么您为什么要检查这些值是否等于空的 String
  • 你说的很对,就是这样。

标签: ruby nomethoderror


【解决方案1】:

从修复程序开始。首先,您说您正在接受字符串数组,但if a1 == '' || a2 == '' 会检查您是否传递了空字符串。输入-1,而不是return -1 基本上没有任何作用。

我假设错误在这一行(你在堆栈跟踪中有一行,它是main.rb:10:in 'mxdiflg',因此第 10 行适合你):

a_total = a1_order.reverse[0].length - a2_order[0].length

好像你的数组是空的,你的array[0] 将是nil 所以你不能在它上面调用.length(就像你粘贴的错误所说的那样)。

至于调试,在某些时候您必须习惯使用Pry,但现在检查行号和错误消息就足够了。在这种情况下,很明显您在nil 上调用.length,因此您的a1_order[0] 必须是nil,因此您的数组必须为空。您还可以添加简单的 puts 消息,例如:

puts "a1_order: #{a1_order}"
puts "a2_order: #{a2_order}"
a_total = a1_order.reverse[0].length - a2_order[0].length
b_total = a2_order.reverse[0].length - a1_order[0].length

现在在运行程序时,您可以检查已排序的数组,并且应该很清楚您正在尝试调用 nils 上的方法。

现在,有了这些,我们可以尝试使您的程序更好一点。首先,正如我所提到的,您的第一次检查没有多大意义。让我们把它变成:

return -1 if [a1,a2].any?(&:empty)

如果任何数组为空,它实际上将从您的方法返回 -1

更进一步:

a1_order = a1.sort{|left, right| left.length <=> right.length}

可以写成:

a1_order.sort_by(&:length)

打电话

a1_order.reverse[0]

效率有点低,因为它会以相反的顺序创建数组的副本,你可以简单地使用a1_order.last

如果要查找最大值/最小值,您可以像这样使用Enumerable#max_by / Enumerable#min_by

a_total = a1.max_by(&:length).length - a2.min_by(&:length).length
b_total = a2.max_by(&:length).length - a1.min_by(&:length).length

通过Array#max可以获得更高的价值:

[a_total, b_total].max

将所有这些包装在一起,您的方法可能如下所示:

def mxdiflg(a1, a2)
  return -1 if [a1, a2].any?(&:empty?)

  a_total = a1.max_by(&:length).length - a2.min_by(&:length).length
  b_total = a2.max_by(&:length).length - a1.min_by(&:length).length

  [a_total, b_total].max
end

【讨论】:

  • 这样更好,而且没有错误,感谢您解释这些方法。
【解决方案2】:

其中一个问题是您如何检查空数组。

irb(main):002:0> [] == ''
=> false

即使数组为空,也总是返回 false。空的?是检查空数组的一种方法,见下文。

#!/usr/bin/ruby

    def run

    p  mxdiflg(["aa" , "b" , "c"], ["dddf", "r", "u", "ee"] )
    p  mxdiflg([], ["f", "r", "u", "ee"] )


    end


    def mxdiflg(a1, a2)

      # return whatever you want if any of the arrays is empty
      return false  if  a1.empty?  || a2.empty?

      # drop empty elements form array
      a1.reject!(&:empty?)
      a2.reject!(&:empty?)

      a1_order = a1.sort{|left, right| left.length <=> right.length}
      a2_order = a2.sort{|left, right| left.length <=> right.length}

      a_total = a1_order.reverse[0].length - a2_order[0].length
      b_total = a2_order.reverse[0].length - a1_order[0].length

      (b_total > a_total) ? b_total : a_total

    end


    run

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多