<< Оператор добавляет строку в список действующих странных - Ruby - PullRequest
0 голосов
/ 30 апреля 2019

Я пытаюсь добавить строку (состоящую из символов из другой строки, повторяемой в цикле for) в массив. Но по какой-то причине, когда я выводил элементы массива в конце, они все отключены.

Вот мой вывод для кода, который у меня есть:

r
racecar
a
aceca
c
cec
e
c
a
r
Final list:
racecar
racecar
acecar
acecar
cecar
cecar
ecar
car
ar
r

Я попытался добавить пустую строку в конец моего оператора, вот так:

list << string_current + ""

и, похоже, проблема решена. Кто-нибудь знает, почему это так?

def longest_palindrome(s)
  n = s.length
  max_string = ""
  max_string_current = ""
  string_current = ""
  list = []
  counter = 0
  for i in (0...n)
    for j in (i...n)
      string_current << s[j]
      # puts "string_current: #{string_current}"
      if is_palindrome(string_current)
        counter += 1
        puts string_current
        list << string_current
      end
    end
    string_current = ""
  end
  puts "Final list:"
  list.each do |item|
    puts "#{item}"
  end
end

def is_palindrome(string)
  for i in (0..string.length/2)
    if string[i] != string[string.length-1-i]
      return false
    end
  end
  return true
end

longest_palindrome("racecar")

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

list << string_current

Ответы [ 2 ]

3 голосов
/ 30 апреля 2019

This:

string_current << s[j]

изменяет строку на месте.Это означает, что это:

list << string_current

может поместить правильную строку в list, а затем эту строку можно изменить позже.

Когда вы добавляете пустую строку:

list << string_current + ""

вы создаете новую строку (string_current + ""), а затем помещаете эту новую строку в list, чтобы вы делалиэто:

tmp = string_current + ""
list << tmp

Несколько простых способов решения вашей проблемы - явное дублирование строки:

if is_palindrome(string_current)
  counter += 1
  puts string_current
  list << string_current.dup # <--------------------
end

или использование += вместо << на string_current:

for i in (0...n)
  string_current = ''
  for j in (i...n)
    string_current += s[j]

Вам также следует подумать о замене ваших for циклов (которые редко встречаются в Ruby) методами из Enumerable.Я не хочу сейчас проходить кроличью нору по рефакторингу, поэтому оставлю это в качестве упражнения для читателя.

0 голосов
/ 30 апреля 2019

Вы также можете исправить это с помощью

list << string_current.dup

но настоящая проблема в вашем

string_current << s[j]

Попробуйте (например, в irb ) следующий пример:

list=[]
str='ab'
list << str
str << 'x'
puts list

Вы увидите, что список теперь содержит 'abx', а не 'ab'.

Причина в том, что список содержит ссылку на объект (указатель) на строку, и когда вы делаете str << 'x', вы не создаете новый объект, а изменяете существующий, и list, следовательно, видит обновленная версия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...