2017-06-30 2 views
1

ich ein Array habeGruppierung Subarrays in Array mit dem gleichen Artikel Rubin

arr = [["cat", "15"], ["dog", "17"], ["cat", "20"], ["cat", "356"], ["dog", "89"], ["bird", "65"], ["dog", "336"], ["bird", "545"]] 

ich durch das gleiche erste Element der Gruppe Subarrays will, ich brauche nur so etwas zu bekommen:

arr = [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65","545"]] 

Kann jemand helfen?

+2

Start mit 'group_by' –

+0

Was Sie bisher versucht haben? – Stefan

+3

_ "** group ** subarrays ** by ** das gleiche ** first ** item" _ → 'group_by (&: first)' sollte dir den Einstieg erleichtern – Stefan

Antwort

2

Das nächste Mal, es wäre toll, wenn Sie einige Schritte hinzufügen, werden Sie versucht wurde, zu tun zu bekommen, was Sie wollen, hier ist eine schnelle Lösung:

> arr.group_by(&:shift).map(&:flatten) 
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]] 

Aber wird diese mutieren original arr

@ Md.FarhanMemon haben gute Lösung ohne mutieren

+2

Es lohnt sich, einen Vorbehalt hinzuzufügen, der das ursprüngliche Array mutiert. –

+2

ja, wir brauchen tiefe duplex hier. Und dieser tut nichts :) –

+0

aber implementieren Sie es nicht. Lassen Sie ihn _etwas _ zu tun :) –

2

Alternative Lösung, ändert sich nicht Original-Objekt, nicht dup brauchen ..

arr.group_by(&:first).map{ |k, v| [k] + v.map { |e| e[1] } } 
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]] 

ODER

arr.group_by(&:first).map{ |k, v| [k] + v.map(&:last) } 
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]] 
+0

oder '[k] + v.map (&: last)' oder 'v.map (&: last) .unshift (k)' – Stefan

+0

Ich habe deine Antwort bearbeitet, weil ich das angenommen habe '|' war ein Tippfehler, aber vielleicht war es 'Array # |'? – Stefan

+0

@Stefan es war kein Tippfehler :) und ja es kann mehrere Variationen geben, um den zweiten Teil abzubilden. 'V.map (&: last)' sieht kürzer aus, obwohl –

1

Ein anderer Weg ist, indem alle Werte in Hash-Zugabe:

animals = arr.each_with_object(Hash.new{|h, k| h[k] = []}) do |(animal_name, value), obj| 
    obj[animal_name] << value 
end 
#=> {"cat"=>["15", "20", "356"], "dog"=>["17", "89", "336"], "bird"=>["65", "545"]} 

Und dann wandelt es in erwartete Ausgabe:

animals.map(&:flatten) 
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]] 
2

Die anderen Antworten perfekt bieten bereits feine Lösungen. Ich poste dieses, um eine Anwendung für die Methode (wenig bekannt?) assoc anzuzeigen. Es durchsucht das Array nach einem Subarray mit dem angegebenen ersten Element, fast so, als wäre das Array ein Hash. Dies kann ein Ergebnis verwendet wird array zu füllen: kann

result = [] 
arr.each do |name, value| 
    group = result.assoc(name) 
    if group 
    group << value 
    else 
    result << [name, value] 
    end 
end 

result 
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]] 

Der Code weiter zu kurzgeschlossen sein:

arr.each_with_object([]) do |(name, value), result| 
    group = result.assoc(name) 
    group ? group << value : result << [name, value] 
end 
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]] 

assoc kann auch leicht verwendet werden, um die Werte für einen bestimmten „Schlüssel“ abrufen aus dem result Array:

name, *values = result.assoc('cat') 
name #=> "cat" 
values #=> ["15", "20", "356"] 
+0

Ordentlich. Ich denke, das ist die effizienteste Lösung. – Gerry

Verwandte Themen