如何重构这个Ruby代码,旨在将哈希的符号更改为字符串?

时间:2010-07-30 09:18:15

标签: ruby refactoring

我刚写了这段代码,但我对此并不满意。

data = {}
options.each{ |k,v| data.merge!({k.to_s => v}) }

基本上我有:

{:a => "something", :b => "something else", :c => "blah"}

......我想......

{"a" => "something", "b" => "something else", "c" => "blah"}

...为了将它发送到由于某种原因不处理符号的gem。在我编写的代码中,选项是原始哈希,数据是更新的,但如果我只能使用1个变量,那就更好了。

你们如何重构我的代码?

5 个答案:

答案 0 :(得分:6)

data = Hash[options.map{ |k,v| [k.to_s,v] }]

对于足够有趣的哈希值,答案之间没有显着差异

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)

答案 1 :(得分:3)

注入似乎赢了:

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

给出

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)

答案 2 :(得分:1)

我建议这样的事情:

hsh = data.inject({}) { |h, (k, v)| h[k.to_s] = v; h }

(取自a similar SO question

答案 3 :(得分:1)

Rails为Hash添加了stringify_keys方法。如果你不使用Rails,你可以简单地从ActiveSupport复制代码(开源ftw!):

def stringify_keys
  inject({}) do |options, (key, value)|
    options[key.to_s] = value
    options
  end
end

答案 4 :(得分:0)

借助activesupport gem,您可以创建一个新哈希(或转换现有哈希),其中字符串和哈希键可以互换。

#!/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