3 Stimmen

Ich habe ein Ruby-Array von Objekten, wie man dieses Array in mehrere Arrays auf der Grundlage der Eigenschaft dieser Objekte ändern?

Was ist der beste Weg, um ein großes Array in mehrere Unterarrays zu ändern, die auf der Eigenschaft der Objekte im ursprünglichen Array basieren? Zum Beispiel habe ich ein Array von Objekten (alle Objekte haben die gleichen Eigenschaften):

array = [
    {:name => "Jim", :amount => "20"},
    {:name => "Jim", :amount => "40"},
    {:name => "Jim", :amount => "30"},
    {:name => "Eddie", :amount => "7"},
    {:name => "Eddie", :amount => "12"},
    {:name => "Pony", :amount => "330"},
    {:name => "Pony", :amount => "220"},
    {:name => "Pony", :amount => "50"}
]

Beachten Sie, dass alle Objekte mit demselben Name Eigenschaft sind in dem Array aufeinanderfolgend. Jetzt möchte ich die Objekte in Unter-Arrays gruppieren, die auf der Eigenschaft name basieren. Was ich brauche ist:

result = [
    [
        {:name => "Jim", :amount => "20"},
        {:name => "Jim", :amount => "40"},
        {:name => "Jim", :amount => "30"}
    ],
    [
        {:name => "Eddie", :amount => "7"},
        {:name => "Eddie", :amount => "12"}
    ],
    [
        {:name => "Pony", :amount => "330"},
        {:name => "Pony", :amount => "220"},
        {:name => "Pony", :amount => "50"}
    ]
]

Wie kann man das am besten machen? Danke!

9voto

mu is too short Punkte 411765

Utilice group_by für die schweren Arbeiten und dann map um das Gewünschte herauszuholen:

result = array.group_by { |h| h[:name] }.map { |k, v| v }

Zum Beispiel:

>> results = array.group_by { |h| h[:name] }.map { |k, v| v }
>> pp results
[[{:name=>"Jim", :amount=>"20"},
  {:name=>"Jim", :amount=>"40"},
  {:name=>"Jim", :amount=>"30"}],
 [{:name=>"Eddie", :amount=>"7"},
  {:name=>"Eddie", :amount=>"12"}],
 [{:name=>"Pony", :amount=>"330"},
  {:name=>"Pony", :amount=>"220"},
  {:name=>"Pony", :amount=>"50"}]]

Sie können auch die map und gehen Sie direkt zu Hash#values :

result = array.group_by { |h| h[:name] }.values

Der Dank geht an KandadaBoggu für den Hinweis auf dieses Versehen.

2voto

KL-7 Punkte 44382

Wenn Hashes mit demselben :name Wert immer aufeinanderfolgende Elemente sind, kann man das auch so machen:

result = array.each_with_object([]) do |e, memo|
  if memo.last && memo.last.last[:name] == e[:name]
    memo.last << e
  else
    memo << [e] 
  end 
end

oder Sie können verwenden Enumerable#chunk (wiederum unter Berücksichtigung der Tatsache, dass Elemente mit demselben :name Wert sind aufeinanderfolgend):

result = array.chunk{ |e| e[:name] }.map(&:last)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X