Reputation: 49
Below is the exercise I’m working on.
Should return the sentence where every curse word has it's vowels replaced with '*'" do
Example #1 censor("Gosh darn it", ["gosh", "darn", "shoot"]) =>("G*sh d*rn it")
Example #2 censor("SHUT THE FRONT DOOR", ["door"]) =>("SHUT THE FRONT D**R")
Where I’m stumped is how to account for the caps. I originally started to loop through each word, but can’t figure out the best way to use something like .include to check if that word was in the array.
I started with the below
def censor(sentence, curse)
vowels = "aeiouAEIOU"
result = ""
words = sentence.split(' ')
new_curse = curse.join(",")
p new_curse.downcase
p words
words.each.with_index do ???
if word.casecmp?()
word.each_char do |char|
if vowels.include?(char)
result << "*"
else
result << char
end
end
else
result << word
end
end
return result
end
Upvotes: 1
Views: 71
Reputation: 110685
There is no need to break the string into words, edit each word and then join them back together to form a new string.
def censor(sentence, coarse_words)
sentence.gsub(/\p{L}+/) { |word|
coarse_words.include?(word.downcase) ? word.gsub(/[aeiou]/i, '*') : word }
end
censor "Gosh darn it", ["gosh", "darn", "shoot"]
#=> "G*sh d*rn it"
censor "SHUT THE FRONT DOOR AFTER YOUR ARE OUTDOORS", ["door"]
#=> "SHUT THE FRONT D**R AFTER YOUR ARE OUTDOORS"
For readers unfamiliar with \p{L}
, search Regexp for it. It's the same as \p{Alpha}
and [[:alpha:]]
, which are documented in the same file.
If there were a large amount of text to be filtered, it would be more efficient to create a set of coarse words:
require 'set'
def censor(sentence, coarse_words)
coarse_words_set = coarse_words.to_set
sentence.gsub(/\p{L}+/) { |word|
coarse_words_set.include?(word.downcase) ? word.gsub(/[aeiou]/i, '*') : word }
end
If, in addition, the list of coarse words were static, one might make the set of coarse words a constant:
require 'set'
COARSE_WORDS = ["gosh", "darn", "shoot"].to_set
def censor(sentence)
sentence.gsub(/\p{L}+/) { |word|
COARSE_WORDS.include?(word.downcase) ? word.gsub(/[aeiou]/i, '*') : word }
end
Upvotes: 1
Reputation: 773
Probably a ton of ways to do this, that's what's fun about coding. Here's one way if you want to use regex. The vowel substitution is case insensitive so it takes care of that issue:
sentence = "Darn, DARN! I forgot my pizza. SHOOT, flip this!"
bwords = %w(darn shoot flip) #cuss words to censor
censored = [] #array for the result
words = sentence.split(" ")
for word in words
word = word.gsub(/[aeiou]/i, "*") if bwords.include? word.downcase.gsub(/[^a-z0-9\s]/, '')
censored.push(word) #put censored word in new array
end
puts censored.join(' ')
Outputs:
D*rn, D*RN! I forgot my pizza. SH**T, fl*p this!
Upvotes: 0
Reputation: 16222
If you take advantage of ruby's builtins, this can be done more elegantly:
def censor(sentence, curse)
curse_re = Regexp.new(Regexp.union(curse).source, 'i')
sentence.split(' ').map do |word|
curse_re.match(word) ? word.gsub(/[aeiou]/i, '*') : word
end.join(' ')
end
This works for both your test cases: Try it online!
The i
flag makes the vowels ignore case, and the curse_re
will match any of the curse words, also ignoring case.
For future reference, you'll get better responses for this kind of question on the SE codereview site.
Upvotes: 0
Reputation: 49
Here is what I ended up with, maybe there's a better way to do it, so if so please let me know. I was caught up with the lowercase, upcase, first character upcase, when I should have just got a pen and pencil and worked through it.
def get_stared(word)
vowels = "aeiou"
result = ""
word.each_char do |char|
if vowels.include?(char.downcase)
result += "*"
else
result += char
end
end
result
end
def censor(sentence, curse_words)
words = sentence.split(" ")
new_words = words.map do |word|
if curse_words.include?(word.downcase)
get_stared(word)
else
word
end
end
new_words.join(" ")
end
Upvotes: 0