
Question:
I just wrote this piece of code but I'm not quite happy about it.
data = {} options.each{ |k,v| data.merge!({k.to_s => v}) }
Basically I have:
{:a => "something", :b => "something else", :c => "blah"}
... and I want ...
{"a" => "something", "b" => "something else", "c" => "blah"}
... in order to send it to a gem that do not handle symbols for some reason. In the code I wrote options is the original hash and data is the updated one, but if I could only use 1 variable it'd be even better.
How would you guys refactor my code?
Solution:1
data = Hash[options.map{ |k,v| [k.to_s,v] }]
For a hash large enough to be interesting, there isn't a significant difference between the answers
require 'benchmark' options = Hash[('aaaa'..'zzzz').map{|i| [i.to_sym,i]}] Benchmark.bm(100) do |x| x.report("map") {Hash[options.map{ |k,v| [k.to_s,v] }] } x.report("zip") {Hash[options.keys.map(&:to_s).zip(options.values)]} x.report("inject") {options.inject({}) { |h, (k, v)| h[k.to_s] = v; h }} end user system total real map 3.490000 0.090000 3.580000 ( 4.049015) zip 3.780000 0.020000 3.800000 ( 3.925876) inject 3.710000 0.110000 3.820000 ( 4.289286)
Solution:2
Inject seems to win:
require 'benchmark' a = {:a => "something", :b => "something else", :c => "blah"} Benchmark.bm(10000) do |x| x.report("map") {Hash[a.map{ |k,v| [k.to_s,v] }] } x.report("zip") {Hash[a.keys.map(&:to_s).zip(a.values)]} x.report("inject") {a.inject({}) { |h, (k, v)| h[k.to_s] = v; h }} end
gives
user system total real map 0.000000 0.000000 0.000000 ( 0.000033) zip 0.000000 0.000000 0.000000 ( 0.000018) inject 0.000000 0.000000 0.000000 ( 0.000014)
Solution:3
I'd suggest something like this:
hsh = data.inject({}) { |h, (k, v)| h[k.to_s] = v; h }
(Taken from a similar SO question)
Solution:4
Rails adds a stringify_keys
method to Hash. If you don't use Rails, you can simply copy the code from ActiveSupport (open source ftw!):
def stringify_keys inject({}) do |options, (key, value)| options[key.to_s] = value options end end
Solution:5
With the aid of the activesupport gem, you can make a new hash (or convert an existing one) wherein string and hash keys are interchangeable.
#!/usr/bin/ruby1.8 require 'active_support' h = HashWithIndifferentAccess.new({'a'=>1, :b=>2}) p h[:a] => 1 p h['a'] => 1 p h[:b] => 2 p h['b'] => 2
Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
EmoticonEmoticon