Использование слова в массив, Рубин


Я просматриваю вопросы Ruby Prep Академии приложений, и я хочу знать, почему это решение работает. Похоже, что массив слов никогда не изменяется, и все же метод работает. Это сбой в матрице, или он прямо у меня под носом?

def capitalize_words(string)
  words = string.split(" ")

  idx = 0
  while idx < words.length
    word = words[idx]
    word[0] = word[0].upcase
    idx += 1
  end

  return words.join(" ")
end
3 3

3 ответа:

String#[]= это мутирующая операция. Для иллюстрации приведем краткую выдержку из вашего кода:

word = "foo"
word[0] = word[0].upcase  # <-- verbatim from your code
word #=> "Foo"

word это все тот же точный объект, содержащийся в массиве words (массивы просто содержат ссылки на объекты, а не данные внутри них), но он был мутирован на месте. Обычно лучше избегать мутаций, когда это возможно, поскольку это делает неочевидным то, что происходит (как вы можете видеть).

Ваш код также может быть написан более лаконично использование map & capitalize (и без всяких мутаций):

string.split(' ').map(&:capitalize).join(' ')

Метод работает потому, что word содержит ссылку на позицию массива. Поэтому, когда вы назначаете:

word = words[idx]

Вы просто используете word в качестве сокращения для работы с этим элементом массива, который модифицируется:

word[0] = word[0].upcase

--

Кроме того, если вы хотите вернуться к этому ответу после изучения некоторых Ruby, вот упрощенная версия метода:

def capitalize_words(string)
  string.split.map(&:capitalize).join(' ')
end

word = word[idx] создает копию ваших данных. Затем он изменит эту копию вместо слов в исходном массиве.

Простое решение будет следующим:

def capitalize_words(string)
  words = string.split(" ")

  idx = 0
  while idx < words.length
    words[idx][0] = words[idx][0].upcase
    idx += 1
  end

  return words.join(" ")
end