Question

I was solving a coding problem to do a funny case for each word, "LiKe ThIs". Here was my one liner solution. I know it's a little hacky, but oh well.

string.split(" ").map{|word| word.split("").map.with_index{|char,i|
  i.even? ? char.upcase! : char.downcase! }.join("")}.join(" ")

This was outputting HLO TEE TS for the input hello there test, making it look like only the even case was firing. But on throwing a print statement in there, I can see that yes, it's going through each index.

In my frustration, I changed it to:

 string.split(" ").map{|word| word.split("").map.with_index{|char,i|
   i.even? ? char = char.upcase : char = char.downcase }.join("")}.join(" ")

which I feel like should be equivalent - changing the char.upcase! to char = char.upcase...And magically, this worked.

What is going on here?

Was it helpful?

Solution

This is due to the definition of upcase! and downcase!. Here's upcase!

Upcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII region.

Notice that it returns nil if no changes were made. In this case, if the character you are iterating over is already in the correct case, it'll return nil and effectively remove the character from the string as part of your map function.

In your specific example, you'll notice every other character is being removed because it's already in lower case and downcase! is returning nil.

OTHER TIPS

Consider writing your code more clearly:

string = 'foo bar'
string.split.map{ |w|
  w.split('').map.with_index{ |char, i|
    i.even? ? char.upcase : char.downcase 
  }.join
}.join(' ')
# => "FoO BaR"

Or, even like this:

string.split.map{ |w|

  w.split('').map.with_index{ |char, i|
    if i.even? 
      char.upcase 
    else
      char.downcase 
    end
  }.join

}.join(' ')
# => "FoO BaR"

Ternary statements should be used judiciously. In languages like C and Perl you'll find them used often, but in Ruby their use is often discouraged, simply because they can be harder to read/understand. If/when you use them, do so with maintenance and readability in mind.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top