Führen Sie zwei Arrays in Ruby zusammen und verschachteln Sie sie

106

Ich habe folgenden Code:

a = ["Cat", "Dog", "Mouse"]
s = ["and", "&"]

Ich möchte das Array sin ein Array zusammenführen, adas mir Folgendes geben würde:

["Cat", "and", "Dog", "&", "Mouse"]

Wenn ich mir die Ruby Array- und Enumerable-Dokumente ansehe, sehe ich keine solche Methode, mit der dies erreicht werden kann.

Gibt es eine Möglichkeit, dies zu tun, ohne jedes Array zu durchlaufen?

Chris Ledet
quelle
a wird immer 3 Elemente haben und s zwei? Einige weitere Beispiele wären nützlich.
tokland

Antworten:

171

Sie können das tun mit:

a.zip(s).flatten.compact
DigitalRoss
quelle
4
Was ist, wenn amehr als 3 Elemente vorhanden sind?
Michael Kohl
116
["a", "b"] .concat (["c", "d"]) # => ["a", "b", "c", "d"]
Leo Romanovsky
30
@Leo, @chuck: Wenn Sie das Beispiel lesen, werden Sie sehen, dass Chris die Elemente verschachteln und nicht verketten möchte . Im Wesentlichen möchte er, [a, s].transposedass die beiden Zeilen nicht übereinstimmen, was #zipals offensichtliche Lösung bleibt. Und ich glaube nicht, dass er meinte, dass es ihn wirklich interessierte, ob er amutiert war ... Ich glaube nicht, dass er eine mutierte oder funktionale Lösung kommentierte, er versuchte nur, das Muster zu beschreiben.
DigitalRoss
15
+1 für die einzige Person, die die Blummin-Frage tatsächlich gelesen hat! > _ <
Matt Fletcher
5
Was ist noch wichtiger, wenn die beiden Arrays ungleich lang sind? Besonders wenn s das längere ist? Ich glaube, ich kann davon ausgehen, dass das Beispiel, das Chris gegeben hat, nicht die tatsächlichen Daten sind, mit denen er arbeitet. Bedenken Sie: [] .zip [1, 2] => nil (es wird schwierig sein, #flatten darauf aufzurufen) [3,4] .zip ([1, 3, 5, 7]) => [[3 , 1], [4, 3]] (oops, schätze, wir kümmern uns nicht um die letzten paar Elemente im 2. Array)
hoff2
32

Dies ergibt kein Ergebnisarray in der von Chris angeforderten Reihenfolge, aber wenn die Reihenfolge des resultierenden Arrays keine Rolle spielt, können Sie es einfach verwenden a |= b. Wenn Sie nicht mutieren möchten a, können Sie a | bdas Ergebnis schreiben und einer Variablen zuweisen.

Weitere Informationen finden Sie in der Dokumentation zur Set Union für die Array-Klasse unter http://www.ruby-doc.org/core/classes/Array.html#M000275 .

Diese Antwort setzt voraus, dass Sie keine doppelten Array-Elemente möchten. Wenn Sie doppelte Elemente in Ihrem endgültigen Array zulassen möchten, a += bsollten Sie den Trick ausführen. Wenn Sie nicht mutieren möchten a, verwenden Sie erneuta + b das Ergebnis und weisen Sie es einer Variablen zu.

In Reaktion auf einige Kommentare auf dieser Seite funktionieren diese beiden Lösungen mit Arrays beliebiger Größe.

Michael Stalker
quelle
Dieser scheint definitiv der beste zu sein.
Ardavis
11
Dies gibt ["Cat", "Dog", "Mouse", "and", "&"], was das OP nicht wollte.
Andrew Grimm
Hervorragender Anruf, Andrew. Ich werde meine Antwort aktualisieren, um zu sagen, dass ich Chris 'Frage nicht beantwortet habe.
Michael Stalker
28

Wenn Sie kein Duplikat möchten, verwenden Sie einfach die Union Operator:

new_array = a | s
Douglas
quelle
1
Verleihung einer +1 für eine unterschätzte, einfache und elegante Lösung.
Giacomo1968
Natürlich beantwortet es die Frage! Die Frage war: "Ich möchte die Arrays in Array a zusammenführen"
Douglas
Gute Lösung - aber das ändert die Reihenfolge der Ergebnisse. Die Ergebnisse von swerden am Ende des neuen Arrays angezeigt.
Hendrik
1
Die Reihenfolge der Elemente entspricht jedoch nicht den Wünschen des OP.
Tokand
6
s.inject(a, :<<)

s   #=> ["and", "&"]
a   #=> ["Cat", "Dog", "Mouse", "and", "&"]

Es gibt Ihnen nicht die Reihenfolge, nach der Sie gefragt haben, aber es ist eine gute Möglichkeit, zwei Arrays durch Anhängen an das eine zusammenzuführen.


quelle
Ich mag es, kurz und sauber. :)
Nafaa Boutefer
6

Hier ist eine Lösung, mit der mehrere Arrays unterschiedlicher Größe verschachtelt werden können (allgemeine Lösung):

arr = [["Cat", "Dog", "Mouse", "boo", "zoo"],
 ["and", "&"],
 ["hello", "there", "you"]]

first, *rest = *arr; first.zip(*rest).flatten.compact
=> ["Cat", "and", "hello", "Dog", "&", "there", "Mouse", "you", "boo", "zoo"]
Abdo
quelle
2
Nett! Eine Einschränkung: Das erste Array muss das längste sein.
Brian Low
@BrianLow toller Fang!
Abdo
5

Es ist nicht gerade elegant, aber es funktioniert für Arrays jeder Größe:

>> a.map.with_index { |x, i| [x, i == a.size - 2 ? s.last : s.first] }.flatten[0..-2] 
#=> ["Cat", "and", "Dog", "&", "Mouse"]
Michael Kohl
quelle
+1 für den Umgang mit seltsamen Randfällen, denke ich, i = s.cycle; a.map { |x| [x, i.next] }.flatten[0..-2]wäre jedoch genauso gültig.
Mu ist zu kurz
Ich war mir nicht sicher, ob OP abwechseln will andund &deshalb nahm ich ihn so wörtlich wie möglich, wobei ich ajede Länge zuließ.
Michael Kohl
3

Wie wäre es mit einer allgemeineren Lösung, die auch dann funktioniert, wenn das erste Array nicht das längste ist und eine beliebige Anzahl von Arrays akzeptiert?

a = [
    ["and", "&"],
    ["Cat", "Dog", "Mouse"]
]

b = a.max_by(&:length)
a -= [b]
b.zip(*a).flatten.compact

 => ["Cat", "and", "Dog", "&", "Mouse"]
Mike
quelle
2

Um die Situation zu bewältigen, in der beide a& snicht gleich groß sind:

a.zip(s).flatten.compact | s
  • .compactwird entfernt, nilwenn agrößer als ists
  • | sfügt die verbleibenden Elemente ab dem sZeitpunkt hinzu, an dem akleiner als ists
Shubham Chaudhary
quelle
1

Eine Möglichkeit, das Interleave durchzuführen und zu gewährleisten, welches das größte Array für die Zip-Methode ist, besteht darin, eines der Arrays nilbis zur anderen Arraygröße zu füllen . Auf diese Weise garantieren Sie auch, welches Element von welchem ​​Array an erster Stelle steht:

preferred_arr = ["Cat", "Dog", "Mouse"]
other_arr = ["and","&","are","great","friends"]

preferred_arr << nil while preferred_arr.length < other_arr.length
preferred_arr.zip(other_arr).flatten.compact
#=> ["Cat", "and", "Dog", "&", "Mouse", "are", "great", "friends"]
Joao Cunha
quelle
1
Etwas besser: preferred_arr.zip(other_arr).flatten | other_arr(ohne die Nullfüllung)
Adam Fendley
-2
arr = [0, 1]
arr + [2, 3, 4]

//outputs [0, 1, 2, 3, 4]
David Morrow
quelle
5
Entschuldigung ... habe die spezifische Reihenfolge, in der Sie die Ausgabe wünschen, nicht bemerkt. Entschuldigung, dass Sie versucht haben zu helfen, wird nicht wieder vorkommen.
David Morrow