Orie Orie - 6 months ago 19
Ruby Question

Advancing Vowel to the Next Vowel in Ruby

I'm working on beginner Ruby tutorials. I'm trying to write a method that will advance vowels to the next vowel. 'a' will become 'e', 'e' will become 'i', 'u' will become 'a', etc etc. I've been trying various ideas for quite a while, to no avail.

I think I'm on the right track in that I need to create an array of the vowels, and then use an index to advance them to the next array in the vowel. I just can't seem to create the right method to do so.

I know this isn't workable code, but my outline is along these lines. Where I run into issues is getting my code to recognize each vowel, and advance it to the next vowel:

def vowel_adv(str)
vowels = ["a", "e", "i", "o", "u"]

str = str.split('')
**str_new = str.map do |letter|
if str_new.include?(letter)
str_new = str_new[+1]
end**
# The ** section is what I know I need to find working code with, but keep hitting a wall.
str_new.join
end


Any help would be greatly appreciated.

Answer

Here's your code with the fewest corrections necessary to make it work:

def vowel_adv(str)
  vowels = ["a", "e", "i", "o", "u"]
  str = str.split('')
  str_new = str.map do |char|
    if vowels.include?(char)
      vowels.rotate(1)[vowels.index(char)]
    else
      char
    end
  end
  str_new.join
end
vowel_adv "aeiou"
=> "eioua"

Things that I changed include

  • addition of a block variable to the map block
  • returning the thing you're mapping to from the map block
  • include? is called on the Array, not on the possible element
  • finding the next vowel by looking in the array of vowels, not by incrementing the character, which is what I think you were trying to do.

Here's an improved version:

VOWELS = %w(a e i o u)
ROTATED_VOWELS = VOWELS.rotate 1

def vowel_adv(str)
  str.
    chars.
    map do |char|
      index = VOWELS.index char
      if index
        ROTATED_VOWELS[index]
      else
        char
      end
    end.
    join
end
  • static Arrays in constants
  • nicer array-of-string syntax
  • String#chars instead of split
  • use the index to test for inclusion instead of include?
  • no assignment to parameters, which is a little confusing
  • no temporary variables, which some people like and some people don't but I've done here to show that it's possible

And, just because Ruby is fun, here's a different version which copies the string and modifies the copy:

VOWELS = %w(a e i o u)
ROTATED_VOWELS = VOWELS.rotate 1

def vowel_adv(str)
  new_str = str.dup
  new_str.each_char.with_index do |char, i|
    index = VOWELS.index char
    if index
      new_str[i] = ROTATED_VOWELS[index]
    end
  end
  new_str
end
Comments