2011-12-20 14 views
5

Me está costando entender la lógica que necesitaría para combinar dos matrices de hashes. Parece que he pedido t his question a while back de una manera diferente, también he intentado algunas otras cosas como las respuestas ofrecido aquí: merging arrays of hashes¿Raíles que combinan dos matrices de hashes?

Cualquier tipo de ayuda entendiendo esto sería realmente útil para mí.

Decir que tengo la siguiente matriz, y esta es la salida del método en sí, por lo que se puede imaginar esos :timestamp s para ser Time objetos

[ 
    {:timestamp=>2011-12-19 00:00:00 UTC}, 
    {:timestamp=>2011-12-19 01:00:00 UTC}, 
    {:timestamp=>2011-12-19 02:00:00 UTC}, 
    {:timestamp=>2011-12-19 03:00:00 UTC}, 
    {:timestamp=>2011-12-19 04:00:00 UTC}, 
    {:timestamp=>2011-12-19 05:00:00 UTC} 
] 

Y entonces una matriz adicional como este, cada uno de los cuales tiene otro valor (pero a veces puede tener un montón más valores, además de :count)

[ 
    {:timestamp=>2011-12-19 02:00:00 UTC, :count=>5}, 
    {:timestamp=>2011-12-19 04:00:00 UTC, :count=>21} 
] 

Y desembocar en algo como esto:

[ 
    {:timestamp=>2011-12-19 00:00:00 UTC}, 
    {:timestamp=>2011-12-19 01:00:00 UTC}, 
    {:timestamp=>2011-12-19 02:00:00 UTC, :count=>5}, 
    {:timestamp=>2011-12-19 03:00:00 UTC}, 
    {:timestamp=>2011-12-19 04:00:00 UTC, :count=>21}, 
    {:timestamp=>2011-12-19 05:00:00 UTC} 
] 

De nuevo, gracias por su ayuda, no estoy seguro de por qué no puedo encontrar el patrón de diseño adecuado para esto.

Respuesta

23

parece que primer grupo por fecha y hora, y luego fusionar los valores:

(a1+a2).group_by{|h| h[:timestamp]}.map{|k,v| v.reduce(:merge)} 
+1

Puede eliminar '' Y en el último bloque de código más corto: 'v.reduce (: merge)'. – htanata

+0

Esto. Buen trabajo :) – d11wtq

+0

@htanata - Sí, tienes razón, actualicé. – pguardiario

2
a = [ 
    {:timestamp=>'2011-12-19 00:00:00 UTC'}, 
    {:timestamp=>'2011-12-19 01:00:00 UTC'}, 
    {:timestamp=>'2011-12-19 02:00:00 UTC'}, 
    {:timestamp=>'2011-12-19 03:00:00 UTC'}, 
    {:timestamp=>'2011-12-19 04:00:00 UTC'}, 
    {:timestamp=>'2011-12-19 05:00:00 UTC'} 
] 

b = [ 
    {:timestamp=>'2011-12-19 02:00:00 UTC', :count=>5}, 
    {:timestamp=>'2011-12-19 04:00:00 UTC', :count=>21} 
] 

result = a.inject([]) do |memo, v| 
    if match = b.detect { |w| (w.to_a & v.to_a).any? } 
    memo << match.merge(v) 
    else 
    memo << v 
    end 
end 

p result 
2

dado que está utilizando el atributo :timestamp de cada uno de hash como su "llave", es fácil si en realidad convertir las matrices en los hashes con la propiedad :timestamp como la clave:

h1 = Hash[a1.map{|h| [h[:timestamp], h]}] 
h2 = Hash[a2.map{|h| [h[:timestamp], h]}] 

Entonces, lo que quiere reduce simplemente a merge -ing los dos valores hash (y salirse con las teclas que se han añadido):

p h1.merge(h2).values 
# => [ 
# {:timestamp=>"2011-12-19 00:00:00 UTC"}, 
# {:timestamp=>"2011-12-19 01:00:00 UTC"}, 
# {:timestamp=>"2011-12-19 02:00:00 UTC", :count=>5}, 
# {:timestamp=>"2011-12-19 03:00:00 UTC"}, 
# {:timestamp=>"2011-12-19 04:00:00 UTC", :count=>21}, 
# {:timestamp=>"2011-12-19 05:00:00 UTC"} 
#]