web-dev-qa-db-fra.com

Comment pouvez-vous ajouter un tableau à un autre tableau dans Ruby et ne pas vous retrouver avec un résultat multidimensionnel?

somearray = ["some", "thing"]

anotherarray = ["another", "thing"]

somearray.Push(anotherarray.flatten!)

J'esperais

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

Vous avez une idée réalisable, mais le #flatten! est au mauvais endroit - il aplatit son récepteur, vous pouvez donc l'utiliser pour transformer [1, 2, ['foo', 'bar']] en [1,2,'foo','bar'].

J'oublie sans doute quelques approches, mais vous pouvez concaténer:

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

ou prepend/append:

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

ou épissure:

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

ou ajouter et aplatir:

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

Vous pouvez simplement utiliser l'opérateur +!

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]

Vous pouvez lire tout sur la classe array ici: http://Ruby-doc.org/core/classes/Array.html

197
micmoo

La méthode la plus propre consiste à utiliser la méthode Array # concat ; il ne créera pas de nouveau tableau (contrairement à Array # + qui fera la même chose mais créera un nouveau tableau).

Directement à partir de la documentation ( http://www.Ruby-doc.org/core-1.9.3/Array.html#method-i-concat ):

concat (other_ary)

Ajoute les éléments de other_ary à soi-même.

Alors

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

Le tableau # concat n'écrasera pas un tableau multidimensionnel s'il est passé en argument. Vous devrez gérer cela séparément:

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

Enfin, vous pouvez utiliser notre gem corelib ( https://github.com/corlewsolutions/corelib ) qui ajoute des aides utiles aux classes de base Ruby. En particulier, nous avons une méthode Array # add_all qui aplatira automatiquement les tableaux multidimensionnels avant d'exécuter le concat.

63
Corlew Solutions

Méthode simple fonctionnant avec Ruby version> = 2.0 mais pas avec les versions antérieures:

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

Essayez ceci, il va combiner vos tableaux pour supprimer les doublons

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

array3 = array1|array2

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

Documentation complémentaire sur "Set Union"

32
g00se0ne

Voici deux manières, notez dans ce cas que la première façon assigne un nouveau tableau (se traduit par 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

De cette façon, vous obtenez les éléments de array1 en premier. Vous n'obtiendrez aucun doublon.

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

Pour ajouter b à a et stocker le résultat dans a:

a.Push(*b)

ou

a += b

Dans les deux cas, a devient:

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

mais dans le premier cas, les éléments de b sont ajoutés au tableau a existant, et dans le dernier cas, les deux tableaux sont concaténés et le résultat est stocké dans a.

13
snibbets

En développant la réponse de @ Pilcrow, la seule réponse appropriée pour les tableaux de grande taille est concat (+) car elle est rapide et n'alloue pas un nouvel objet à récupérer lors de son fonctionnement dans une boucle.

Voici le repère:

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

Résultats:

       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)

Comme vous pouvez le voir avec Push jette un ERREUR: stack level too deep (SystemStackError) lorsque les tableaux sont suffisamment grands.

9
juliangonzalez

La question essentielle consiste à savoir "comment concaténer des tableaux en Ruby". Naturellement, la solution consiste à utiliser concat ou + comme indiqué dans presque toutes les réponses.

Une extension naturelle de la question serait "comment effectuer une concaténation par rangée de tableaux 2D en Ruby". Lorsque j'ai cherché "Matrices de concaténation" dans Google, cette question SO était le meilleur résultat. J'ai donc pensé laisser ma réponse à cette question (non demandée mais liée) ici pour la postérité.


Dans certaines applications, vous pouvez vouloir "concaténer" deux tableaux 2D par rangée. Quelque chose comme,

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

C'est quelque chose comme "augmenter" une matrice. Par exemple, j'ai utilisé cette technique pour créer une seule matrice d'adjacence afin de représenter un graphique à partir d'un groupe de matrices plus petites. Sans cette technique, j'aurais dû parcourir les composants d'une manière qui aurait pu être source d'erreurs ou frustrante. J'aurais peut-être dû faire un each_with_index, par exemple. Au lieu de cela, j'ai combiné Zip et aplatir comme suit,

# 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

Juste une autre façon de le faire.

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

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

5
samg

Si les nouvelles données peuvent être un tableau ou un scalaire et que vous souhaitez empêcher l'imbrication des nouvelles données s'il s'agissait d'un tableau, l'opérateur Splat est génial! Il retourne un scalaire pour un scalaire et une liste non compressée d'arguments pour un tableau.

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

Je suis surpris que personne n'ait mentionné reduce, ce qui fonctionne bien lorsque vous avez un tableau de tableaux:

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

Cela ne supprimera pas les bêtises, mais

a|b

enlève les dups.

3
AustintheCleric

Je trouve plus facile de pousser ou d’ajouter des tableaux, puis de les aplatir, comme ceci:

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