Array of hashes to hash

后端 未结 7 605
遥遥无期
遥遥无期 2020-12-12 15:20

For example, I have array of single hashes

a = [{a: :b}, {c: :d}]

What is best way to convert it into this?

{a: :b, c: :d}
         


        
相关标签:
7条回答
  • 2020-12-12 16:00

    You can use .inject:

    a.inject(:merge)
    #=> {:a=>:b, :c=>:d}
    

    Demonstration

    Which initiates a new hash on each iteration from the two merged. To avoid this, you can use destructive :merge!( or :update, which is the same):

    a.inject(:merge!)
    #=> {:a=>:b, :c=>:d}
    

    Demonstration

    0 讨论(0)
  • 2020-12-12 16:02

    Try this

    a.inject({}){|acc, hash| acc.merge(hash)} #=> {:a=>:b, :c=>:d}
    
    0 讨论(0)
  • 2020-12-12 16:11

    I came across this answer and I wanted to compare the two options in terms of performance to see which one is better:

    1. a.reduce Hash.new, :merge
    2. a.inject(:merge)

    using the ruby benchmark module, it turns out that option (2) a.inject(:merge) is faster.

    code used for comparison:

    require 'benchmark'
    
    input = [{b: "c"}, {e: "f"}, {h: "i"}, {k: "l"}]
    n = 50_000
    
    Benchmark.bm do |benchmark|
      benchmark.report("reduce") do
        n.times do
          input.reduce Hash.new, :merge
        end
      end
    
      benchmark.report("inject") do
        n.times do
          input.inject(:merge)
        end
      end
    end
    

    the results were

           user     system      total        real
    reduce  0.125098   0.003690   0.128788 (  0.129617)
    inject  0.078262   0.001439   0.079701 (  0.080383)
    
    0 讨论(0)
  • 2020-12-12 16:14

    You may use

    a.reduce Hash.new, :merge
    

    which directly yields

    {:a=>:b, :c=>:d}
    

    Note that in case of collisions the order is important. Latter hashes override previous mappings, see e.g.:

    [{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge   # {:a=>:g, :c=>:d, :e=>:f}
    
    0 讨论(0)
  • 2020-12-12 16:14

    Just use

    a.reduce(:merge)
    #=> {:a=>:b, :c=>:d}
    
    0 讨论(0)
  • 2020-12-12 16:14

    You can transform it to array [[:a, :b]] and after that translate everything to hash {:a=>:b}

    # it works like [[:a, :b]].to_h => {:a=>:b}
    
    [{a: :b}, {c: :d}].map { |hash| hash.to_a.flatten }.to_h
    
    # => {:a=>:b, :c=>:d}
    
    0 讨论(0)
提交回复
热议问题