tags:

views:

42

answers:

3

I want to convert the name "JOHN DOE-SMITH" to "John Doe-Smith" using the code:

name = "JOHN DOE-SMITH"  
name_split = name.split(/\s/)  
name_split.each do |x|  
  if x =~ /-/  
    name1, name2 = x.split(/-/)  
    x = name1.capitalize + "-" + name2.capitalize  
  else  
    x.capitalize!  
  end  
end  
puts name_split.join(" ")  

The result is the unexpected "John DOE-SMITH"
Why does x.capitalize! have an effect while x = "foo" has none?
Is there a better way to do this?

+1  A: 

x = "foo" just assigns the variable x to reference a different object. Since that variable only exists in the block, this has no observable effect. It doesn't change the string at all. x.capitalize!, on the other hand, sends the capitalize! message to the string, which causes it to change case.

Chuck
A: 

Because x is a local variable that points to a string using the same data. This is why affecting a new value to it doesn't change inside the string.

You might want to rethink a little your strategy here ; it is dependant on the fact that the split string refers to the same memory area as the original string, which I wouldn't bet holds true in all cases.
I'd suggest to use .map instead:

name_split = name.split(/\s/).map do |x|
  if x =~ /-/
    name1, name2 = x.split(/-/)
    name1.capitalize + "-" + name2.capitalize
  else
    x.capitalize
  end
end  
puts name_split.join(" ")

Or if you find this more readable:

name_split = name.split(/\s/).map do |x|
  x.split(/-/).map(&:capitalize).join('-')
end
puts name_split.join(" ")
Jean
A: 

How about

cap_name = name.split.map{|w| w.split("-").map(&:capitalize).join("-") }.join(" ")
Jonas Elfström