(Вступительное примечание: Обычно вы не хотите изменять объект Enumerable во время итерации по нему, поскольку это усложняет чтение кода и его отладку.)
Ваш to_tut не сохраняетВаши изменения, потому что блочная переменная "c" является копией фрагмента строки, а не ссылкой на часть строки (если бы это был ref, вы могли бы использовать << для добавления; "+ =" по-прежнемуне сработает, потому что он переназначает, а не меняет ссылку).Именно так работает each_char, так как строка не содержит ссылок. </p>
Если вы хотите изменить строку на месте, вам, вероятно, придется считать в обратном порядке, а затем вставлять 'ut' по индексу через строкузнак равноНо это очень сложно, поэтому я представлю несколько альтернатив.
Работа to_tut # 1:
def self.to_tut string
string.chars.map do |c|
yield c if block_given?
# this must be the last expression the block
if @@consonants.find { |i| i == c.downcase }
c + 'ut'
else
c
end
end.join
end
Работа to_tut # 2 - это, вероятно, самый рубиновый способ сделать это:
def self.to_tut string
string.gsub(/[#{@@consonants.join}]/i) {|match|
yield match if block_given?
# this must be the last expression in the block
match + 'ut'
}
end
Ваш to_english не работает, потому что array.shift всегда удаляет первый элемент массива.Вместо этого вы хотите отследить текущий индекс и удалить 2 символа, начиная с индекса + 1.
Работа to_english:
def self.to_english2 string
array = string.split //
array.each_with_index do |c, idx|
if @@consonants.find { |i| i == c.downcase }
array.slice!(idx+1, 2)
end
yield c if block_given?
end
array.join
end
Относительно того, почему ваш "put lan" возвращает один символ на строку- это потому что ваш to_english возвращает массив.Вы захотите позвонить в join, чтобы преобразовать его.