How do I convert a Ruby hash so that all of its keys are symbols?

后端 未结 15 1791
不思量自难忘°
不思量自难忘° 2020-12-04 19:01

I have a Ruby hash which looks like:

{ \"id\" => \"123\", \"name\" => \"test\" }

I would like to convert it to:

{ :id         


        
相关标签:
15条回答
  • 2020-12-04 19:27

    If you are using Rails >= 4 you can use:

    hash.deep_symbolize_keys
    hash.deep_symbolize_keys!
    

    or

    hash.deep_stringify_keys
    hash.deep_stringify_keys!
    

    see http://apidock.com/rails/v4.2.1/Hash/deep_symbolize_keys

    0 讨论(0)
  • 2020-12-04 19:30

    Victor Moroz provided a lovely answer for the simple recursive case, but it won't process hashes that are nested within nested arrays:

    hash = { "a" => [{ "b" => "c" }] }
    s2s[hash] #=> {:a=>[{"b"=>"c"}]}
    

    If you need to support hashes within arrays within hashes, you'll want something more like this:

    def recursive_symbolize_keys(h)
      case h
      when Hash
        Hash[
          h.map do |k, v|
            [ k.respond_to?(:to_sym) ? k.to_sym : k, recursive_symbolize_keys(v) ]
          end
        ]
      when Enumerable
        h.map { |v| recursive_symbolize_keys(v) }
      else
        h
      end
    end
    
    0 讨论(0)
  • 2020-12-04 19:30

    Here's my two cents,

    my version of symbolize_keys_deep! uses the original symbolize_keys! provided by rails and just makes a simple recursive call to Symbolize sub hashes.

      def symbolize_keys_deep!(h)
        h.symbolize_keys!
        h.each do |k, v|
          symbolize_keys_deep!(v) if v.is_a? Hash
        end
      end
    
    0 讨论(0)
  • 2020-12-04 19:31

    Here's a Ruby one-liner that is faster than the chosen answer:

    hash = {"apple" => "banana", "coconut" => "domino"}
    #=> {"apple"=>"banana", "coconut"=>"domino"}
    
    hash.inject({}){|h,(k,v)| h[k.intern] = v; h}
    #=> {:apple=>"banana", :coconut=>"domino"}
    

    Benchmark results:

    n = 100000
    
    Benchmark.bm do |bm|
      bm.report { n.times { hash.inject({}){|h,(k,v)| h[k.intern] = v; h} } }
      bm.report { n.times { Hash[hash.map{ |k, v| [k.to_sym, v] }] } }
    end
    
    # =>       user     system      total        real
    # =>   0.100000   0.000000   0.100000 (  0.107940)
    # =>   0.120000   0.010000   0.130000 (  0.137966)
    
    0 讨论(0)
  • 2020-12-04 19:34

    Facets' Hash#rekey is also a worth mentioning.

    Sample:

    require 'facets/hash/rekey'
    { "id" => "123", "name" => "test" }.deep_rekey
    => {:id=>"123", :name=>"test"}
    

    There is also a recursive version:

    require 'facets/hash/deep_rekey'
    { "id" => "123", "name" => {"first" => "John", "last" => "Doe" } }.deep_rekey
    => {:id=>"123", :name=>{:first=>"John", :last=>"Doe"}}
    
    0 讨论(0)
  • 2020-12-04 19:34

    Here's a little recursive function to do a deep symbolization of the keys:

    def symbolize_keys(hash)
      Hash[hash.map{|k,v| v.is_a?(Hash) ? [k.to_sym, symbolize_keys(v)] : [k.to_sym, v] }]
    end
    
    0 讨论(0)
提交回复
热议问题