开发者

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 = "开发者_如何学Gofoo" has none?

Is there a better way to do this?


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.


How about

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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜