Joe Horn
Joe Horn

Reputation: 49

Parsing an array to find individual word, capitalization is relevant

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

Answers (4)

Cary Swoveland
Cary Swoveland

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

Bman70
Bman70

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

Jonah
Jonah

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

Joe Horn
Joe Horn

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

Related Questions