it-swarm.com.de

Wie fügt man ein Array einem anderen Array in Ruby hinzu und erhält kein mehrdimensionales Ergebnis?

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.Push(anotherarray.flatten!)

Ich erwartete

["some","thing","another","thing"]
440
ncvncvn

Sie haben eine brauchbare Idee, aber der #flatten! befindet sich an der falschen Stelle - er plattiert seinen Empfänger, sodass Sie ihn verwenden können, um [1, 2, ['foo', 'bar']] in [1,2,'foo','bar'] umzuwandeln.

Ich vergesse zweifellos einige Ansätze, aber Sie können verketten:

a1.concat a2
a1 + a2              # creates a new array, as does a1 += a2

oder voranstellen/anhängen:

a1.Push(*a2)         # note the asterisk
a2.unshift(*a1)      # note the asterisk, and that a2 is the receiver

oder Spleiß:

a1[a1.length, 0] = a2
a1[a1.length..0] = a2
a1.insert(a1.length, *a2)

oder anhängen und reduzieren:

(a1 << a2).flatten!  # a call to #flatten instead would return a new array
665
pilcrow

Sie können einfach den Operator + verwenden!

irb(main):001:0> a = [1,2]
=> [1, 2]
irb(main):002:0> b = [3,4]
=> [3, 4]
irb(main):003:0> a + b
=> [1, 2, 3, 4]

Sie können hier alles über die Array-Klasse lesen: http://Ruby-doc.org/core/classes/Array.html

197
micmoo

Am saubersten ist es, die Array # concat -Methode zu verwenden. Es wird kein neues Array erstellt (im Gegensatz zu Array # +, das dasselbe tut, aber ein neues Array erstellt).

Direkt aus den Dokumenten ( http://www.Ruby-doc.org/core-1.9.3/Array.html#method-i-concat ):

concat (other_ary)

Hängt die Elemente von other_ary an self an.

Damit

[1,2].concat([3,4])  #=> [1,2,3,4]  

Array # concat reduziert ein mehrdimensionales Array nicht, wenn es als Argument übergeben wird. Das müssen Sie separat erledigen:

arr= [3,[4,5]]
arr= arr.flatten   #=> [3,4,5]
[1,2].concat(arr)  #=> [1,2,3,4,5]

Zuletzt können Sie unser Corelib-Juwel ( https://github.com/corlewsolutions/corelib ) verwenden, das den Ruby -Kernklassen nützliche Helfer hinzufügt. Insbesondere haben wir eine Array # add_all Methode, die mehrdimensionale Arrays automatisch reduziert, bevor das concat ausgeführt wird.

63

Einfache Methode, die mit Ruby Version> = 2.0 funktioniert, jedoch nicht mit älteren Versionen:

irb(main):001:0> a=[1,2]
=> [1, 2]
irb(main):003:0> b=[3,4]
=> [3, 4]
irb(main):002:0> c=[5,6]
=> [5, 6]
irb(main):004:0> [*a,*b,*c]
=> [1, 2, 3, 4, 5, 6]
33
Ludovic Kuty

Versuchen Sie dies, es wird Ihre Arrays kombinieren und Duplikate entfernen

array1 = ["foo", "bar"]
array2 = ["foo1", "bar1"]

array3 = array1|array2

http://www.Ruby-doc.org/core/classes/Array.html

Weitere Dokumentation siehe "Set Union"

32
g00se0ne

Hier sind zwei Möglichkeiten: Beachten Sie in diesem Fall, dass die erste Möglichkeit ein neues Array zuweist (übersetzt in somearray = somearray + anotherarray).

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray += anotherarray # => ["some", "thing", "another", "thing"]

somearray = ["some", "thing"]
somearray.concat anotherarray # => ["some", "thing", "another", "thing"]
27
Joshua Cheek

(array1 + array2).uniq

Auf diese Weise erhalten Sie zuerst die Elemente array1. Sie erhalten keine Duplikate.

20
slindsey3000
a = ["some", "thing"]
b = ["another", "thing"]

So hängen Sie b an a an und speichern das Ergebnis in a:

a.Push(*b)

oder

a += b

In beiden Fällen wird a zu:

["some", "thing", "another", "thing"]

im ersten Fall werden die Elemente von b an das vorhandene a -Array angehängt, und im zweiten Fall werden die beiden Arrays miteinander verkettet und das Ergebnis in a gespeichert.

13
snibbets

Auf die Antwort von @ Pilcrow einzugehen, ist die einzig geeignete Antwort für große Arrays concat (+), da sie schnell ist und kein neues Objekt zuweist, das beim Betrieb in einer Schleife mit Müll gesammelt werden soll.

Hier ist der Maßstab:

require 'benchmark'

huge_ary_1 = Array.new(1_000_000) { Rand(5_000_000..30_000_00) }

huge_ary_2 = Array.new(1_000_000) { Rand(35_000_000..55_000_00) }

Benchmark.bm do |bm|
  p '-------------------CONCAT ----------------'
  bm.report { huge_ary_1.concat(huge_ary_2) }

  p '------------------- Push ----------------'
  bm.report { huge_ary_1.Push(*huge_ary_2)  }
end

Ergebnisse:

       user     system      total        real
"-------------------CONCAT ----------------"
  0.000000   0.000000   0.000000 (  0.009388)
"------------------- Push ----------------"
  example/array_concat_vs_Push.rb:13:in `block (2 levels) in <main>': stack level too deep (SystemStackError)

Wie Sie sehen können, löst Push einen ERROR: stack level too deep (SystemStackError) aus, wenn die Arrays groß genug sind.

9
juliangonzalez

Die Frage lautet im Wesentlichen "Wie werden Arrays in Ruby verkettet?". Natürlich ist die Antwort, concat oder + zu verwenden, wie in fast jeder Antwort erwähnt.

Eine natürliche Erweiterung der Frage wäre "wie man eine zeilenweise Verkettung von 2D-Arrays in Ruby durchführt". Als ich "Ruby Concatenate Matrizen" gegoogelt habe, war diese SO Frage das beste Ergebnis, also dachte ich, ich würde meine Antwort auf diese (nicht gestellte, aber verwandte) Frage der Nachwelt überlassen.


In einigen Anwendungen möchten Sie möglicherweise zwei 2D-Arrays zeilenweise "verketten". So etwas wie,

[[a, b], | [[x],    [[a, b, x],
 [c, d]] |  [y]] =>  [c, d, y]]

Dies ist so etwas wie das "Erweitern" einer Matrix. Ich habe diese Technik zum Beispiel verwendet, um eine einzelne Adjazenzmatrix zu erstellen, die einen Graphen aus einer Reihe kleinerer Matrizen darstellt. Ohne diese Technik hätte ich die Komponenten auf eine Weise durchlaufen müssen, die fehleranfällig oder frustrierend gewesen wäre. Ich hätte zum Beispiel einen each_with_index machen müssen. Stattdessen habe ich Zip und Flatten wie folgt kombiniert:

# given two multi-dimensional arrays that you want to concatenate row-wise
m1 = [[:a, :b], [:c, :d]]
m2 = [[:x], [:y]]

m1m2 = m1.Zip(m2).map(&:flatten)
# => [[:a, :b, :x], [:c, :d, :y]]
8
Ziggy

Nur eine andere Art, es zu tun.

[somearray, anotherarray].flatten
=> ["some", "thing", "another", "thing"]
8
Datt

["some", "thing"] + ["another" + "thing"]

5
samg

Wenn die neuen Daten ein Array oder ein Skalar sein könnten und Sie verhindern möchten, dass die neuen Daten verschachtelt werden, wenn es sich um ein Array handelt, ist der splat-Operator fantastisch! Es gibt einen Skalar für einen Skalar und eine entpackte Liste von Argumenten für ein Array zurück.

1.9.3-p551 :020 > a = [1, 2]
 => [1, 2] 
1.9.3-p551 :021 > b = [3, 4]
 => [3, 4] 
1.9.3-p551 :022 > c = 5
 => 5 
1.9.3-p551 :023 > a.object_id
 => 6617020 
1.9.3-p551 :024 > a.Push *b
 => [1, 2, 3, 4] 
1.9.3-p551 :025 > a.object_id
 => 6617020 
1.9.3-p551 :026 > a.Push *c
 => [1, 2, 3, 4, 5] 
1.9.3-p551 :027 > a.object_id
 => 6617020 
4

Ich bin überrascht, dass niemand reduce erwähnt hat, was gut funktioniert, wenn Sie eine Reihe von Arrays haben:

lists = [["a", "b"], ["c", "d"]]
flatlist = lists.reduce(:+)  # ["a", "b", "c", "d"]
4
ScottJ
a = ['a', 'b']
b = ['c', 'd']
arr = [a, b].flatten

Dups werden dadurch nicht entfernt, aber

a|b

entfernt Dups.

3
AustintheCleric

Ich finde es einfacher, Arrays zu pushen oder anzuhängen und sie dann wie folgt zu reduzieren:

somearray = ["some", "thing"]
anotherarray = ["another", "thing"]
somearray.Push anotherarray # => ["some", "thing", ["another", "thing"]]
#or
somearray << anotherarray # => ["some", "thing", ["another", "thing"]]
somearray.flatten!  # => ["some", "thing", "another", "thing"]
somearray # => ["some", "thing", "another", "thing"]
2
nas