Я проверил, что index
в методе не nil
, распечатав его. Я также сделал index == nil
для двойной проверки.
Что мне здесь не хватает?
Не index
это nil
, а new_array
. В сообщении об ошибке написано:
undefined method `<<' for nil:NilClass
и имеется ссылка на строку new_array << index
. Здесь <<
- метод, а new_array
- получатель. И по какой-то причине new_array
равно nil
.
Вы, вероятно, ожидали, что new_array
будет []
, потому что вы явно указали new_array = []
. Но у методов есть своя собственная область видимости локальных переменных. Если вы определяете локальную переменную вне метода, она не будет доступна внутри или наоборот.
Обычно при обращении к неопределенной переменной вы получите:
undefined local variable or method `new_array'
но здесь второе присваивание скрывает реальную проблему:
new_array = array.each do |index|
^^^^^^^^^^^
Когда Ruby встречает эту строку, он немедленно создает локальную переменную new_array
с начальным значением nil
. (локальные переменные создаются, когда строка анализируется, а не когда происходит присваивание)
Чтобы получить ожидаемый результат, вам нужно переместить new_array = []
в метод, получить избавиться от присваивания new_array = array.each { ...}
и вернуть new_array
в конце:
def substrings(word, array)
new_array = []
array.each do |index|
if index.include?(word)
new_array << index
end
end
new_array
end
Имена переменных немного произвольны, возможно, даже вводят в заблуждение. Наличие index.include?(word)
выглядит так, как будто вы сравниваете числовой индекс со строкой. Я бы использовал что-то вроде этого:
def substrings(substring, words)
result = []
words.each do |word|
if word.include?(substring)
result << word
end
end
result
end
По коду вы можете включить массив в l oop через each_with_object
, который также вернет массив:
def substrings(substring, words)
words.each_with_object([]) do |word, result|
if word.include?(substring)
result << word
end
end
end
Однако выбор элементов на основе условия является настолько распространенной задачей, что Ruby предоставляет специальный метод select
- вам просто нужно вернуть true
или false
из блока, чтобы указать, следует ли выбирать элемент:
def substrings(substring, words)
words.select do |word|
word.include?(substring)
end
end