Программа работает, но я все еще получаю NoMethodError 'length' nil - PullRequest
0 голосов
/ 12 ноября 2018

Эта программа берет два массива строк и вычитает длину самого длинного в a1 из самого короткого в a2, а затем наоборот и возвращает большее.

Это работает (прошло 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

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

@ Марчин Колодзей, ты побил меня, но я все еще собираюсь опубликовать свой ответ.@Jules Одна из проблем заключается в том, как вы проверяете наличие пустых массивов.

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
0 голосов
/ 12 ноября 2018

Начиная с исправления вашей программы.Прежде всего, вы говорите, что принимаете массивы строк, но if a1 == '' || a2 == '' проверяет, передали ли вы пустые строки.Ввод -1, а не return -1, по сути, ничего не делает.

Я предполагаю, что ошибка находится в этой строке (у вас есть строка в stacktrace, поэтому main.rb:10:in 'mxdiflg', поэтому строка 10 для вас):

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

Как будто ваш массив пуст, ваш array[0] будет nil, поэтому вы не можете вызвать .length (как подсказывает вставленная вами ошибка).

Что касается отладки, в какой-то момент вам придется освоиться с использованием Pry , но пока этого должно быть достаточно, чтобы вы проверили номер строки и сообщение об ошибке.В этом случае совершенно ясно, что вы вызываете .length для nil, поэтому ваш a1_order[0] должен быть nil, поэтому ваш массив должен быть пустым.Вы также можете добавить сообщения о простом размещении, например:

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
...