jack
jack

Reputation: 63

Ruby assignment inside an iterator

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?

Upvotes: 0

Views: 203

Answers (3)

Jonas Elfström
Jonas Elfström

Reputation: 31428

How about

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

Upvotes: 0

Jean
Jean

Reputation: 10600

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(" ")

Upvotes: 0

Chuck
Chuck

Reputation: 237010

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.

Upvotes: 1

Related Questions