代码之家  ›  专栏  ›  技术社区  ›  marcgg

如何重构此Ruby代码,以将哈希符号更改为字符串?

  •  1
  • marcgg  · 技术社区  · 14 年前

    我刚写了这段代码,但我不太满意。

    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"}
    

    …为了送它到一个宝石,不处理符号,因为某些原因。在我编写的代码中,选项是原始散列值,数据是最新的散列值,但是如果我只能使用1个变量,那就更好了。

    你们如何重构我的代码?

    5 回复  |  直到 14 年前
        1
  •  6
  •   John La Rooy    14 年前
    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)
    
        2
  •  3
  •   hellvinz    14 年前

    注射似乎赢了:

    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)
    
        3
  •  1
  •   Community CDub    8 年前

    我建议这样做:

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

    (取自 a similar SO question )

        4
  •  1
  •   Teoulas    14 年前

    Rails增加了 stringify_keys 要哈希的方法。如果不使用Rails,只需从 ActiveSupport (开源ftw!):

    def stringify_keys
      inject({}) do |options, (key, value)|
        options[key.to_s] = value
        options
      end
    end
    
        5
  •  0
  •   Wayne Conrad    14 年前

    借助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