I am using a hash map to advance the character by position: "a" into "b", etc., and to capitalize vowels.

def LetterChanges(str)
  str.to_s
  puts str
  h = ("a".."z").to_a
  i = ("b".."z").to_a.push("a")
  hash = Hash[h.zip i]
  new_str = str.downcase.gsub(/[a-z]/,hash)
  new_str.gsub!(/[aeiou]/) {|n| n.upcase }
end

LetterChanges("hello world")
LetterChanges("sentence")
LetterChanges("replace!*")
LetterChanges("coderbyte")
LetterChanges("beautiful^")
LetterChanges("oxford")
LetterChanges("123456789ae")
LetterChanges("this long cake@&")
LetterChanges("a b c dee")
LetterChanges("a confusing /:sentence:/[ this is not!!!!!!!~")

The above code works as expected except for the examples "replace!*" and "123456789ae", for which it returns nil. Why is this?

String#gsub! modifies the original string, and returns that string or nil if no replacements were performed.

String#gsub does not modify the original string but always return the result even if nothing was changed.

Either return new_str at the end of your method, or use gsub instead of gsub!.

This is somewhat of a pattern in Ruby - when multiple version of a method exist, the one with ! will modify the receiver and the one without will simply return the result.

As an aside, it looks like you're not using the result of str.to_s for anything. If you know it's a string, to_s is pointless. If it might not be, you should make use of the result, for example like so:

str = str.to_s

String#gsub! returns nil when no substitution is performed.

new_str.gsub!(/[aeiou]/) {|n| n.upcase }

returns nil when new_str doesn't contain any vowel letters. This is the case for example, if str is "replace!*", new_str is sfqmbdf!*, no vowels.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.