dwhipple
dwhipple

Reputation: 39

Capitalizing Vowels in a String with Ruby

I have a method that takes in a string as an argument, replaces each letter with the next letter in the alphabet and then capitalizes every vowel. I have gotten both of those to work individually (the replacing and capitalization), but at this point, I just don't know how to make them work together.

def LetterChanges(str)
    new_str = str.downcase.split("")
    new_str.each do |x|
        x.next!
    end
    new_str.to_s.tr!('aeiou','AEIOU')
    return new_str.join("")
end

LetterChanges("abcdef")

Upvotes: 1

Views: 859

Answers (6)

Baxter
Baxter

Reputation: 142

This can be achieved with the combination of gsub and tr:

"abcdef".gsub(/[A-z]/) { |char| char.next }.tr('aeiou', 'AEIOU')
#=> "bcdEfg"
"Fun times!".gsub(/[A-z]/) { |char| char.next }.tr('aeiou', 'AEIOU')
#=> "GvO Ujnft!"

Upvotes: 0

Charles
Charles

Reputation: 1396

How about:

def string_thing(string)
    string.downcase.tr('abcdefghijklmnopqrstuvwxyz','bcdEfghIjklmnOpqrstUvwxyzA')
end

#tr just will replace each character in the first parameter with the corresponding one in the second parameter.

Upvotes: 0

Stefan
Stefan

Reputation: 114188

Other answers already showed you how to combine both parts of your code. But there's another issue: String#next is continuing witch "aa" after "z":

"z".next #=> "aa"

You could add an if statement to handle this case:

str.chars.map do |char|
  if char == 'z'
    'a'
  else
    char.next
  end
end.join

or:

str.chars.map { |char| char == 'z' ? 'a' : char.next }.join

But there's a much simpler way: let String#tr perform the entire substitution:

str.downcase.tr('a-z', 'bcdEfghIjklmnOpqrstUvwxyzA')

Or slightly shorter:

str.downcase.tr('a-z', 'bcdEfghIjk-nOp-tUv-zA')

Upvotes: 1

Jake Worth
Jake Worth

Reputation: 5852

2.1.0 :012 > 'abcdef'.split('').map(&:next).join.tr('aeiou', 'AEIOU')
 => "bcdEfg"

I would not recommend doing this in one line, of course. But to get at your confusion of how these methods might string together, here is one solution that works. When in doubt, use IRB to call each method and watch how Ruby responds. That will help you figure out where your code is breaking down.

In practice, I would break this into multiple methods. It's too many things for one method to do. And also a lot harder to find bugs (and test), as you found out.

def rotate(string)
  string.split('').map(&:next).join
end

def capitalize_vowels(string)
  string.tr('aeiou', 'AEIOU')
end

Upvotes: 0

Horacio
Horacio

Reputation: 2965

That could be resolved with gsub.

"abcdef".gsub(/./){|char| char.next}.gsub(/[aeiou]/){|vowel| vowel.upcase}
#=> "bcdEfg" 

so that method could be

def letter_changes_gsub(str)
  str.gsub(/./){|char| char.next}.gsub(/[aeiou]/){|vowel| vowel.upcase}
end

That is faster and more simple that work with arrays.

Upvotes: 1

Explosion Pills
Explosion Pills

Reputation: 191749

new_str.to_s is not stored anywhere. It doesn't affect the original array.

return new_str.join("").tr('aeiou', 'AEIOU')

This will convert the array back to a string and you can operate on that and return it.

Upvotes: 4

Related Questions