it-swarm.com.de

Array von Hashes zum Hash

Zum Beispiel habe ich ein Array von einzelnen Hashes

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

Was ist der beste Weg, um es in dieses umzuwandeln?

{a: :b, c: :d}
57
evfwcqcg

Sie können verwenden

a.reduce Hash.new, :merge

was direkt ergibt

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

Beachten Sie, dass bei Kollisionen die Reihenfolge wichtig ist. Letztere Hashes überschreiben frühere Zuordnungen, siehe z.

[{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge   # {:a=>:g, :c=>:d, :e=>:f}
106
Howard

Sie können .inject verwenden:

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

Demonstration

Dadurch wird bei jeder Iteration ein neuer Hash aus den beiden zusammengeführt. Um dies zu vermeiden, können Sie den destruktiven :merge! (oder :update, der gleich ist) verwenden:

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

Demonstration

30
potashin

Diese zwei:

total_hash = hs.reduce({}) { |acc_hash, hash| acc_hash.merge(hash) }
total_hash = hs.reduce({}, :merge)

Beachten Sie, dass Hash#merge bei jeder Iteration einen neuen Hash erstellt. Dies kann ein Problem sein, wenn Sie einen großen Hash erstellen. In diesem Fall verwenden Sie stattdessen update:

total_hash = hs.reduce({}, :update)

Ein alternativer Ansatz wäre, die Hashes in Paare zu konvertieren und dann den endgültigen Hash zu erstellen:

total_hash = hs.flat_map(&:to_a).to_h
21
tokland

Sie können es in Array [[:a, :b]] umwandeln und anschließend alles in Hash {:a=>:b} übersetzen.

# 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
Evan Ross

Ich bin auf diese Antwort gestoßen und wollte die beiden Optionen in Bezug auf die Leistung vergleichen, um herauszufinden, welche besser ist:

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

bei Verwendung des Ruby-Benchmark-Moduls stellt sich heraus, dass Option (2) a.inject(:merge) schneller ist.

code zum Vergleich verwendet:

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

die Ergebnisse waren

       user     system      total        real
reduce  0.125098   0.003690   0.128788 (  0.129617)
inject  0.078262   0.001439   0.079701 (  0.080383)
0
bigsolom

Versuche dies

a.inject({}){|acc, hash| acc.merge(hash)} #=> {:a=>:b, :c=>:d}
0
Rahul Patel

Benutz einfach

a.reduce(:merge)
#=> {:a=>:b, :c=>:d}
0
Ritesh katare