are.include? sentence.downcase
гласит: «Если один из элементов arr
равен sentence.downcase
...», а не то, что вы хотите.
baddies = ["gosh", "it's", "hot", "shoot", "so"]
sentence = "Gosh, it's so very hot"
r = /\b#{baddies.join('|')}\b/i
#=> /\bgosh|it's|hot|shoot|so\b/i
sentence.gsub(r) { |w| w.gsub(/[aeiou]/i, '*') }
#=> "G*sh *t's s* very h*t"
В регулярном выражении \b
- это разрыв слова , а #{baddies.join('|')}
требует совпадения с одним из baddies
. Разрывы слов должны избегать, например, "so"
соответствия "solo"
или "possible"
. В качестве альтернативы можно написать:
/\b#{Regexp.union(baddies).source}\b/
#=> /\bgosh|it's|hot|shoot|so\b/
См. Regexp :: union и Regexp # source . source
необходим, потому что Regexp.union(baddies)
не зависит от модификатора безразличия (i
).
Другой подход состоит в том, чтобы разбить предложение на слова, манипулировать каждым словом, а затем объединить все части, чтобы сформировать новое предложение. Одна из сложностей этого подхода связана с персонажем "'"
, который выполняет двойную функцию в качестве одинарной кавычки и апостроф. Рассмотрим
sentence = "She liked the song, 'don't box me in'"
baddies = ["don't"]
подход, который я здесь дал, дает правильный результат:
r = /\b#{baddies.join('|')}\b/i
#=> /\bdon't\b/i
sentence.gsub(r) { |w| w.gsub(/[aeiou]/i, '*') }
#=> "She liked the song 'd*n't box me in'"
Если вместо этого мы разделим предложение на части, мы можем попробовать следующее:
sentence.split(/([\p{Punct}' ])/)
#=> ["She", " ", "liked", " ", "", " ", "the", " ", "song", ",", "",
# " ", "", "'", "don", "'", "t", " ", "box", " ", "me", " ", "in", "'"]
Как видно, регулярное выражение делится "don't"
на "don"
и "'t"
, а не на то, что мы хотим. Очевидно, что различие между одинарными кавычками и апострофами является нетривиальной задачей. Это затрудняется тем фактом, что слова могут начинаться или заканчиваться апострофами ("'twas"
), а за большинством существительных в притяжательной форме, оканчивающихся на "s"
, следует апостроф ("Chris' car"
).