I tried:
somearray = ["some", "thing"] anotherarray = ["another", "thing"] somearray.push(anotherarray.flatten!) I expected
["some", "thing", "another", "thing"] but got
["some", "thing", nil] You've got a workable idea, but the #flatten! is in the wrong place -- it flattens its receiver, so you could use it to turn [1, 2, ['foo', 'bar']] into [1,2,'foo','bar'].
I'm doubtless forgetting some approaches, but you can concatenate:
a1.concat a2 a1 + a2 # creates a new array, as does a1 += a2 or prepend/append:
a1.push(*a2) # note the asterisk a2.unshift(*a1) # note the asterisk, and that a2 is the receiver or splice:
a1[a1.length, 0] = a2 a1[a1.length..0] = a2 a1.insert(a1.length, *a2) or append and flatten:
(a1 << a2).flatten! # a call to #flatten instead would return a new array Array#concat does not allocate a new array, Concatenation with Array#+ doesconcat! So really the answer should be edited yet again to just have concat as the solution. The other solutions are cool but superfluous.You can just use the + operator!
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] You can read all about the array class here: http://ruby-doc.org/core/classes/Array.html
a+= b creates a new array: c = a = [1,2] ; b = [3,4] ; a += b ; puts c #=> [1,2]push method as described by @pilcrow.+= creates new object. in such example [1, 2].each_with_object([]) { |number, object| object+=number } empty array [] will be returnedThe cleanest approach is to use the Array#concat method; it will not create a new array (unlike Array#+ which will do the same thing but create a new array).
Straight from the docs (http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-concat):
concat(other_ary)
Appends the elements of other_ary to self.
So
[1,2].concat([3,4]) #=> [1,2,3,4] Array#concat will not flatten a multidimensional array if it is passed in as an argument. You'll need to handle that separately:
arr= [3,[4,5]] arr= arr.flatten #=> [3,4,5] [1,2].concat(arr) #=> [1,2,3,4,5] Lastly, you can use our corelib gem (https://github.com/corlewsolutions/corelib) which adds useful helpers to the Ruby core classes. In particular we have an Array#add_all method which will automatically flatten multidimensional arrays before executing the concat.
a = ["some", "thing"] b = ["another", "thing"] To append b to a and store the result in a:
a.push(*b) or
a += b In either case, a becomes:
["some", "thing", "another", "thing"] but in the former case, the elements of b are appended to the existing a array, and in the latter case the two arrays are concatenated together and the result is stored in a.
a.push(*b) is not exactly the same as a += b. The former adds the new elements to the existing array; the latter creates a new array with all elements and assigns it to a. You can see the difference if you do something like aa = a to save the ref to a before either append method and then examine aa afterwards. In the former case, it changes with the new value of a, and in the latter it remains unchanged.each_with_object usage and the like. Doing each_with_object([]) { |thing, result| result += [thing] } will not work, while using the push method does.Easy method that works with Ruby version >= 2.0 but not with older versions :
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] * here?[*a, *b] fails for older versions of ruby, ie, 1.8.7. And as much as Ruby wants to tell you its out of life, RHEL6 is still maintained, making Ruby 1.8 very much a significant target version.[...array1, ...array2], just remembering that the splat operator in ruby would be * instead of .... It makes it easier to rememberHere are two ways, notice in this case that the first way assigns a new array ( translates to 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"] Try this, it will combine your arrays removing duplicates
array1 = ["foo", "bar"] array2 = ["foo1", "bar1"] array3 = array1|array2 http://www.ruby-doc.org/core/classes/Array.html
Further documentation look at "Set Union"
array1 |= [ "foo1", "bar1" ] #=> [ "foo", "bar", "foo1", "bar1" ]["some", "thing"] + ["another", "thing"] [*a] + [*b] works"another" + "thing" is going to work as expected.Elaborating on @Pilcrow's answer the only suitable answer for huge arrays is concat (+) since is fast and does not allocate a new object to be garbage-collected when operating inside a loop.
Here's the benchmark:
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 Results:
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) As you can see using push throws an ERROR: stack level too deep (SystemStackError) when the arrays are big enough.
Just another way of doing it.
[somearray, anotherarray].flatten => ["some", "thing", "another", "thing"] flatten flattens everything as far as possible, recursively. Even nested arrays. Consequently, if somearray or anotherarray contains nested arrays, they get flattened, too. This is a side-effect that is usually not intended.somearray = ["some", "thing"] anotherarray = ["another", "thing"] somearray + anotherarray # => ["some", "thing", "another", "thing"] somearray.concat anotherarray # => ["some", "thing", "another", "thing"] somearray.push(anotherarray).flatten # => ["some", "thing", "another", "thing"] somearray.push *anotherarray # => ["another", "thing", "another", "thing"] The question, essentially, is "how to concatenate arrays in Ruby". Naturally the answer is to use concat or + as mentioned in nearly every answer.
A natural extension to the question would be "how to perform row-wise concatenation of 2D arrays in Ruby". When I googled "ruby concatenate matrices", this SO question was the top result so I thought I would leave my answer to that (unasked but related) question here for posterity.
In some applications you might want to "concatenate" two 2D arrays row-wise. Something like,
[[a, b], | [[x], [[a, b, x], [c, d]] | [y]] => [c, d, y]] This is something like "augmenting" a matrix. For example, I used this technique to create a single adjacency matrix to represent a graph out of a bunch of smaller matrices. Without this technique I would have had to iterate over the components in a way that could have been error prone or frustrating to think about. I might have had to do an each_with_index, for example. Instead I combined zip and flatten as follows,
# 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]] If the new data could be an array or a scalar, and you want to prevent the new data to be nested if it was an array, the splat operator is awesome! It returns a scalar for a scalar, and an unpacked list of arguments for an array.
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 a = ['a', 'b'] b = ['c', 'd'] arr = [a, b].flatten This won't remove dups, but
a|b removes dups.
I find it easier to push or append arrays and then flatten them in place, like so:
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"]
ri Array@flatten!Why this question is getting so many votes? The doc is explicitArray#flatten!Flattens self in place. Returns nil if no modifications were made (i.e., the array contains no subarrays.)flatten!doesn't work like that. Finally, the question reflects a logic problem rather than an optimization problem. See pilcrow's answer below for more.