Brian Moore Brian Moore - 27 days ago 7
Ruby Question

replace words in a string and re join them

Hi I'm building a function that has me take any instance of "u" or "you" in a string and replace it with a specific word. I can go in and isolate the instances no problem but I cannot get the words to output properly. So far I have.

def autocorrect(input)

#replace = [['you','u'], ['your sister']]
#replace.each{|replaced| input.gsub!(replaced[0], replaced[1])}
input.split(" ")

if (input == "u" && input.length == 1) || input == "you"
input.replace("your sister")

input.join(" ")

The ideal output would be:

autocorrect("I am so smitten with you")

"I am smitten with your sister"

I don't know how to get the last part correct, I can't think of a good method to use. Any help would be greatly appreciated.

Answer Source

The problem you're having with your code is that you call input.split(" ") but you don't save that to anything, and then you check for input == "u" # ..., and input is still the entire string, so if you called autocorrect('u') or autocorrect('you') you would get "your sister" back, except for the next line: input.join(" ") will throw an error.

This error is because, remember input is still the original string, not an array of each word, and strings don't have a join method.

To get your code working with the fewest changes possible, you can change it to:

def autocorrect(input)
  #replace = [['you','u'], ['your sister']]
  #replace.each{|replaced| input.gsub!(replaced[0], replaced[1])}
  input.split(" ").map do |word|
    if (word == "u" && word.length == 1) || word == "you"
      "your sister"
  end.join(" ")

So, now, you are doing something with each word after you split(" ") the input, and you are checking each word against "u" and "you", instead of the entire input string. You then map either the replacement word, or the original, and then join them back into a single string to return them.

As an alternative, shorter way, you can use String#gsub which can take a Hash as the second parameter to do substitutions:

If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.

def autocorrect(input)
  replace = { 'you' => 'your sister',
              'u' => 'your sister',
              'another word' => 'something else entirely' }

  input.gsub(/\b(#{replace.keys.join('|')})\b/, replace)

autocorrect("I am u so smitten with utopia you and another word")
# => "I am your sister so smitten with utopia your sister and something else entirely"

the regex in that example comes out looking like:

/\b(you|u|another word)\b/

with \b being any word boundary.