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?


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

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.


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

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.


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"]

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"]

+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"]

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

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"]

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]

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.