Merge and interleave two arrays in Ruby

RubyArrays

Ruby Problem Overview


I have the following code:

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

I want to merge the array s into array a which would give me:

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

Looking through the Ruby Array and Enumerable docs, I don't see such a method that will accomplish this.

Is there a way I can do this without iterating through each array?

Ruby Solutions


Solution 1 - Ruby

You can do that with:

a.zip(s).flatten.compact

Solution 2 - Ruby

This won't give a result array in the order Chris asked for, but if the order of the resulting array doesn't matter, you can just use a |= b. If you don't want to mutate a, you can write a | b and assign the result to a variable.

See the set union documentation for the Array class at http://www.ruby-doc.org/core/classes/Array.html#M000275.

This answer assumes that you don't want duplicate array elements. If you want to allow duplicate elements in your final array, a += b should do the trick. Again, if you don't want to mutate a, use a + b and assign the result to a variable.

In response to some of the comments on this page, these two solutions will work with arrays of any size.

Solution 3 - Ruby

If you don't want duplicate, why not just use the union operator :

new_array = a | s

Solution 4 - Ruby

s.inject(a, :<<)

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

It doesn't give you the order you asked for, but it's a nice way of merging two arrays by appending to the one.

Solution 5 - Ruby

Here's a solution that allows interleaving multiple arrays of different sizes (general solution):

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

Solution 6 - Ruby

It's not exactly elegant, but it works for arrays of any size:

>> a.map.with_index { |x, i| [x, i == a.size - 2 ? s.last : s.first] }.flatten[0..-2] 
#=> ["Cat", "and", "Dog", "&", "Mouse"]

Solution 7 - Ruby

To handle the situation where both a & s are not of the same size:

a.zip(s).flatten.compact | s
  • .compact will remove nil when a is larger than s
  • | s will add the remaining items from s when a is smaller than s

Solution 8 - Ruby

How about a more general solution that works even if the first array isn't the longest and accepts any number of arrays?

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

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

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

Solution 9 - Ruby

One way to do the interleave and also guarantee which one is the biggest array for the zip method, is to fill up one of the arrays with nil until the other array size. This way, you also guarantee which element of which array will be on first position:

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

Solution 10 - Ruby

Interleave 2D array of any size

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

max_count = arr.map(&:count).max
max_count.times.map{|i| arr.map{|a| a[i]}}.flatten.compact

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

Solution 11 - Ruby

A very clear way to merge multiple arrays is to unpack them into one array. This works in practically the same way for many languages, so I'd prefer this method due to its simplicity and developer familiarity with it.

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

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

Solution 12 - Ruby

arr = [0, 1]
arr + [2, 3, 4]

//outputs [0, 1, 2, 3, 4]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris LedetView Question on Stackoverflow
Solution 1 - RubyDigitalRossView Answer on Stackoverflow
Solution 2 - RubyMichael StalkerView Answer on Stackoverflow
Solution 3 - RubyDouglasView Answer on Stackoverflow
Solution 4 - Rubyuser131441View Answer on Stackoverflow
Solution 5 - RubyAbdoView Answer on Stackoverflow
Solution 6 - RubyMichael KohlView Answer on Stackoverflow
Solution 7 - RubyShubham ChaudharyView Answer on Stackoverflow
Solution 8 - RubyMikeView Answer on Stackoverflow
Solution 9 - RubyJoao CunhaView Answer on Stackoverflow
Solution 10 - RubyYee YeeView Answer on Stackoverflow
Solution 11 - RubySmartensView Answer on Stackoverflow
Solution 12 - RubyDavid MorrowView Answer on Stackoverflow