views:

61

answers:

2

I'm trying this:

{:id => 5, :foos => [1,2,3]}.each {|k,v| v.to_s}

But that's returning this:

{:id=>5, :foos=>[1, 2, 3]}

I'd like to see this:

{:id=>"5", :foos=>"[1, 2, 3]"}

I've also tried variations of Hash#collect and Hash#map. Any ideas?

+1  A: 

Your stuff doesn't work because v.to_s doesn't modify v, so essentially the block doesn't do anything.

You could do it like this:

hash = {:id => 5, :foos => [1,2,3]}
hash.each_key { |k| hash[k] = hash[k].to_s }

If you don't want to modify the hash:

hash = {:id => 5, :foos => [1,2,3]}
new_hash = {}
hash.each_key { |k| new_hash[k] = hash[k].to_s }    
glebm
@glebm, is there any method that does modify the hash?
macek
I edited the answer to show you how to do it without modifying the hash
glebm
@glebm, i **want** to modify the original hash. I don't need to avoid modifying it :)
macek
the problem is that for an Array like [1, 2, 3], `to_s` returns "123", where `inspect` returns "[1, 2, 3]".
rubiii
@smotchkkiss: The first method does modify the hash.
sepp2k
@sepp2k, I meant the original hash "literal" before setting it to a var. No worries though.
macek
@glebm, thanks for this +1
macek
A: 

you could use Object#inspect:

{ :id => 5, :foos => [1, 2, 3] }.inject({}) do |hash, (key, value)|
  hash.merge key => value.inspect
end

which returns:

{ :foos => "[1, 2, 3]", :id => "5" }

or if you want it to be destructive:

hash = { :id => 5, :foos => [1, 2, 3] }
hash.each_key { |key| hash[key] = hash[key].inspect }
rubiii
@rubiii, **note** in Ruby 1.9, `Array#to_s` produces the same result as `Array#inspect`. I don't know if this was true for previous versions.
macek
@smotchkiss i just tried that using irb on 1.9.1-p378 and .. you're right :) didn't know that. for ruby 1.8.7 though [1,2,3].to_s just returns "123".
rubiii