2012-06-08 63 views

Respuesta

94

Es posible utilizar

a.reduce Hash.new, :merge 

que da directamente

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

Tenga en cuenta que en caso de colisiones el orden es importante. hashes últimos anular asignaciones anteriores, véase, por ejemplo:

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

'Hash.new', o como amigos, como a llámalo, '{}' :-) Tanto como me gusta la solución funcional pura, ten en cuenta que 'merge' creará un nuevo hash en cada iteración; podemos usar 'update' en su lugar (no se equivocará con los hashes de entrada, ese es el punto importante):' hs.reduce ({},: update) ' – tokland

+0

Maravillosamente hecho – Aeramor

+0

@tokland, publique su comentario como algo separado respuesta - debería tener más visibilidad – Jason

19

Esas dos líneas son equivalentes:

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

Tenga en cuenta que Hash#merge crea una nueva almohadilla en cada iteración, que puede ser un problema si usted está construyendo una gran hash. En ese caso, utilice update lugar:

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

Un enfoque alternativo sería la de convertir los hashes a pares y luego construir el último hash:

total_hash = hs.flat_map(&:to_a).to_h 
18

Puede utilizar .inject:

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

Demonstration

Que inicia un nuevo hash en cada iteración de los dos fusionados. Para evitar esto, puede utilizar destructiva :merge! (o :update, que es lo mismo):

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

Demonstration

0

probar este

a.inject({}){|acc, hash| acc.merge(hash)} #=> {:a=>:b, :c=>:d} 
Cuestiones relacionadas