2011-12-20 15 views
5

Ciężko mi zrozumieć logikę potrzebną do scalenia dwóch tablic skrótów. Wygląda na to, że zapytałem t his question a while back w nieco inny sposób. Próbowałem też kilku innych rzeczy, takich jak odpowiedzi oferowane tutaj: merging arrays of hashesSzyny łączące dwie tablice skrótów?

Jakikolwiek rodzaj pomocy w zrozumieniu tego byłby dla mnie bardzo pomocny.

Say mam następujący tablicę, a to jest wyjście z tej samej metody, więc można sobie wyobrazić te :timestamp do bycia Time obiekty

[ 
    {: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} 
] 

a potem dodatkowy tablicy tak, z których każdy ma inna wartość (ale czasami może mieć grono więcej wartości oprócz :count)

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

I spowodować coś takiego:

[ 
    {: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} 
] 

Jeszcze raz, dziękuję za pomoc, nie jestem pewien, dlaczego po prostu nie mogę znaleźć odpowiedniego wzoru do tego.

Odpowiedz

23

wygląda najpierw grupę, datownik, a następnie scalić wartości:

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

Możesz usunąć '&' na ostatnim bloku dla krótszego kodu: 'v.reduce (: merge)'. – htanata

+0

To. Dobra robota :) – d11wtq

+0

@htanata - Tak, masz rację, zaktualizowałem. – 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

Ponieważ używasz atrybut każdego hash jako jego „klucz” :timestamp jest to łatwe, jeśli rzeczywiście konwertować tablice do skrótów z właściwością :timestamp jako klucz:

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

Wtedy, co chcesz zmniejsza się po prostu merge -ing dwa skróty (i unikanie klawiszy):

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"} 
#] 
Powiązane problemy