Сортировка строк в массиве без функции сортировки - Ruby - PullRequest
0 голосов
/ 18 октября 2018

Я пытаюсь создать алгоритм сортировки без функции сортировки в Ruby.Я основал это на идее сортировки вставок.Идея состоит в том, что функция проверяет, являются ли n-е значения каждых двух слов одинаковыми, и если это так, n увеличивается на единицу, пока одно значение не станет больше другого.В этом случае слова могут поменяться.Тем не менее, моя функция продолжает зависать.Есть идеи почему?

words = ["my","favorite","animal", "are", "the", "elephant", "and", "the", "antelope", "and", "the", "favela"]

#Convert all letters into numbers. Output individual words as arrays.
converted_words = words.map(&:chars).map { |letters| letters.map { |letter| letter.to_i 36 } }
puts converted_words.to_s

i = 1
x = 0
while i < converted_words.length
  if converted_words[i][x] == converted_words[i-1][x]
    x = x + 1
  else
    if converted_words[i][x] < converted_words[i-1][x]
      converted_words[i], converted_words[i-1] = converted_words[i-1], converted_words[i]
      i = 0
      x = 0
    else
      i = i + 1
    end
  end
end
puts converted_words.to_s

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Мне кажется, я решил проблему.Спасибо за твою помощь.

Я переупорядочил свой алгоритм: сначала проверяю if converted_words[i][x] < converted_words[i-1][x], а , затем проверяем if converted_words[i][x] == converted_words[i-1][x].

Мне также нужно проверить, действительно ли if converted_words[i][x] != nil && converted_words[i-1][x] != nil, чтобы избежать ошибки NoMethodError (спасибо Cary Swoveland).Наконец, я объединил два алгоритма.

Я также понял, что мне не нужно преобразовывать буквы в числа, поскольку ruby ​​ знает , какие буквы больше.Поэтому вместо этого я оставил символы в виде букв.

Я знаю, что код не очень эффективен.Если у вас есть какие-либо предложения по улучшению или упрощению алгоритма, я буду рад их услышать.

Вот код:

words = ["my","favorite","animals", "are", "the", "elephant", "and", "the", "antelope", "and", "the", "favela"]
puts words.to_s
#Convert all letters into numbers. Output individual words as arrays.
ordered_words = words.map(&:chars).map { |letters| letters.map { |letter| letter } }

i = 1
x = 0
while i < ordered_words.length
  if ordered_words[i][x] != nil && ordered_words[i-1][x] != nil
    if ordered_words[i][x] < ordered_words[i-1][x]
      ordered_words[i], ordered_words[i-1] = ordered_words[i-1], ordered_words[i]
      i = 1
      x = 0
    else
      if ordered_words[i][x] == ordered_words[i-1][x]
        x = x + 1
      else
        i = i + 1
        x = 0
      end
    end
  else
    if ordered_words[i][x] == nil && ordered_words[i-1][x] == nil
      i = i + 1
      x = 0
    else
      if ordered_words[i][x] == nil
        ordered_words[i], ordered_words[i-1] = ordered_words[i-1], ordered_words[i]
        i = 1
        x = 0
      else
        i = i + 1
        x = 0
      end
    end
  end
end

joined_words = []
ordered_words.each do |word|
  joined_words.push(word.join)
end
puts joined_words.to_s
0 голосов
/ 18 октября 2018

Ваш код не "зависает";при его запуске возникает это исключение:

NoMethodError (undefined method '<' for nil:NilClass)

в строке:

if converted_words[i][x] < converted_words[i-1][x]

Мы сразу видим проблему, хотя причина еще не известна.Получатель метода < равен converted_words[i][x].Поскольку в сообщении об ошибке говорится, что nil не имеет метода <, мы заключаем, что converted_words[i][x] равно nil. 1 Это означает, что индекс находится вне допустимого диапазона (примерыиндекс, выходящий за пределы допустимого диапазона: [1,2][412] #=> nil и [1,2][-3] #=> nil).Если бы i было вне диапазона, выражение уменьшилось бы до nil[x] < ..., что привело бы к исключению, что nil не имеет метода NilClass#\[\]].Это не наше сообщение об исключении, поэтому мы заключаем, что x должно быть вне диапазона.

Чтобы понять, почему это происходит, предположим:

words = ["a", "ab"]

Затем

converted_words =
  words.map(&:chars).map { |letters| letters.map { |letter| letter.to_i 36 } }
  #=> [[10], [10, 11]] 
i = 1
x = 0
while i < converted_words.length
  #=> while 1 < 2 => while true, so enter the loop
if converted_words[i][x] == converted_words[i-1][x]
  #=> if converted_words[1][0] == converted_words[0][0] => if 10 == 10 => true

, поэтому выполните

x = x + 1
  #=> x = 0 + 1 => 1

и попытайтесь повторить цикл.

while i < converted_words.length
  #=> while 1 < 2 => while true, so repeat the loop
if converted_words[i][x] == converted_words[i-1][x]
  #=> if converted_words[1][1] == converted_words[0][1] => if 11 == nil => false

, поэтому выполните (else).

if converted_words[i][x] < converted_words[i-1][x]
  #=> converted_words[0][1] < converted_words[-1][1] => if nil < 11
  #=> NoMethodError (undefined method '<' for nil:NilClass)

Сообщения об ошибкахсодержать ценную информацию.Внимательно изучите их!

1 Сообщение об ошибке "nil не имеет метода <" здесь эквивалентно " NilClass не имеет метода экземпляра <".

...