simpler way to modify a string

Viewed 130

I recently solved this problem, but felt there is a simpler way to do it. I'd like to use fewer lines of code than I am now. I'm new to ruby so if the answer is simple I'd love to add it to my toolbag. Thank you in advance.

goal: accept a word as an arg, and return the word with it's last vowel removed, if no vowels - return the original word

def hipsterfy(word)
    vowels = "aeiou"
    i = word.length - 1
    while i >= 0
        if vowels.include?(word[i])
            return word[0...i] + word[i+1..-1]
        end
        i -= 1
    end
    word
end
3 Answers

try this regex magic:

def hipsterfy(word)
  word.gsub(/[aeiou](?=[^aeiou]*$)/, "")
end

how does it work?

[aeiou] looks for a vowel., and ?=[^aeiou]*$ adds the constraint "where there is no vowel match in the following string. So the regex finds the last vowel. Then we just gsub the matched (last vowel) with "".

You could use rindex to find the last vowel's index and []= to remove the corresponding character:

def hipsterfy(word)
  idx = word.rindex(/[aoiou]/)
  word[idx] = '' if idx
  word
end

The if idx is needed because rindex returns nil if no vowel is found. Note that []= modifies word.

There's also rpartition which splits the string at the given pattern, returning an array containing the part before, the match and the part after. By concat-enating the former and latter, you can effectively remove the middle part: (i.e. the vowel)

def hipsterfy(word)
  before, _, after = word.rpartition(/[aoiou]/)
  before.concat(after)
end

This variant returns a new string, leaving word unchanged.

Another common approach when dealing with some last occurrence is to reverse the string so you can deal with a first occurrence instead (which is usually simpler). Here, you can utilize sub:

def hipsterfy(word)
  word.reverse.sub(/[aeiou]/, '').reverse
end

Here is another way to do it.

  1. Reverse the characters of the string

  2. Use find_index to get the first vowel location in this reversed string

  3. Delete the character at this index

  4. Un-reverse the characters and join them back together.

    reverse_chars = str.chars.reverse
    vowel_idx = reverse_chars.find_index { |char| char =~ /[aeiou]/ }
    reverse_chars.delete_at(vowel_idx) if vowel_idx
    result = reverse_chars.reverse.join
    
Related