web-dev-qa-db-fra.com

Tableau de hash à hash

Par exemple, j'ai un tableau de hachages simples

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

Quel est le meilleur moyen de le convertir en cela?

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

Vous pouvez utiliser

a.reduce Hash.new, :merge

qui donne directement

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

Notez qu'en cas de collision, l'ordre est important. Les hachages récents annulent les mappages précédents, voir par exemple:

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

Vous pouvez utiliser .inject:

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

Manifestation

Ce qui initie un nouveau hachage à chaque itération parmi les deux fusionnés. Pour éviter cela, vous pouvez utiliser le :merge! destructeur (ou le :update, qui est identique):

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

Manifestation

30
potashin

Ces deux:

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

Notez que Hash#merge crée un nouveau hachage à chaque itération, ce qui peut poser problème si vous construisez un gros hachage. Dans ce cas, utilisez update à la place:

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

Une autre approche serait de convertir les hachages en paires, puis de construire le hachage final:

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

Vous pouvez le transformer en tableau [[:a, :b]] et ensuite traduire tout en 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
Evan Ross

Je suis tombé sur cette réponse et je voulais comparer les deux options en termes de performances pour voir laquelle est la meilleure:

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

en utilisant le module de référence Ruby, il s’avère que l’option (2) a.inject(:merge) est plus rapide.

code utilisé pour la comparaison:

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

les résultats ont été

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

Essaye ça

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

Juste utiliser

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