2017-01-05 2 views
0

Ich bekomme ein Array mit Objekte. Ein person kann mehrere houses haben:Kürzen Mapping und concat

person.houses => ActiveRecord_Associations_CollectionProxy 

Einige Häuser zu mehreren persons gehören. In meinem Code möchte ich alle eindeutigen houses für die Personen erhalten, die in dem Array sind.

Dies ist eine lange Version des Codes:

def persons_houses(persons) 
    unique_houses = [] 

    persons.each do |person| 
    person.houses.each do |house| 
     unique_houses << house if !unique_houses.include? house 
    end 
    end 

    unique_houses 
end 

Kennen Sie einen kürzeren Code für diese persons_houses(persons) Methode?

ich Häuser des Abbildens der Personen zu denken, concat sie zur gleichen Zeit und dann eindeutige Werte zurückgeben

So etwas wie: (Aber das ist nicht gültig Ruby ist)

persons.map { |person| concat(person.houses) }.uniq 

Vielen Dank für Eure Hilfe!

+0

Dies fühlt sich an, als sollte es in der Datenbankabfrage geschehen, nicht in einem Ruby-Array. Verstehe ich richtig, dass Sie eine Viele-zu-Viele-Beziehung zwischen Haus und Person haben? Wenn ja, wird es als has_and_belongs_to_many oder has_many: through implementiert? – moveson

Antwort

1

Jede Person hat viele Häuser, und ein einzelnes Haus kann zu vielen Menschen gehören? Wie wäre es:

persons.map(&:houses).flatten.uniq 
+0

Dies funktioniert, aber es erstellt ein unnötiges Array, das abhängig vom Dataset sehr groß sein kann. – moveson

0

Sie können mit einer einzigen Datenbank-Abfrage dies zu tun, und ohne ein Array zu machen bis hin zu analysieren. Vorausgesetzt Sie haben eine Beziehungstabelle (nicht sicher, wie sonst eine Person viele Häuser haben und ein Haus kann viele Personen haben), und vorausgesetzt, Ihr Beziehungstabelle ownerships genannt wird, würden Sie tun:

House.joins(:ownerships).where(ownerships: {person_id: persons.ids}).uniq 

Dies ist wesentlich schneller und viel mehr Speicher effizienter als die andere Antwort vorgeschlagen, und es hinterlässt Sie mit einer ActiveRecord_Relation, so dass Sie das Ergebnis weiter einschränken können.