Rails merge array into array of arrays

Viewed 56

I'm new to Ruby on Rails and I have a weird array situation that I'm unable to figure out how to execute efficiently.

I have this starting array of arrays:

[["6884", true], ["8456", false], ["5631", false]]

Then I have another 1D array:

["6884", "8023", "9837"]

I want to merge the 1D array into the array of arrays by appending the value to the end of the array at the same index in the 2D array.

So the final product should be:

[["6884", true, "6884"], ["8456", false, "8023"], ["5631", false, "9837]]

So the value at index 0 in the 1D array is appended to the end of the array at index 0 in the 2D array, and so on for each element in the 1D array. Is there an easy Ruby way to accomplish this?

4 Answers

You can do it with zip and flatten methods like this:

a = [["6884", true], ["8456", false], ["5631", false]]
b = ["6884", "8023", "9837"]

a.zip(b)
# [[["6884", true], "6884"], [["8456", false], "8023"], [["5631", false], "9837"]]

# Then use flatten to this array:
a.zip(b).map(&:flatten)
# [["6884", true, "6884"], ["8456", false, "8023"], ["5631", false, "9837"]]

Further to Mehmet Adil İstikbal's answer, here's another approach -- just to show that There's More Than One Way To Do It:

a = [["6884", true], ["8456", false], ["5631", false]]
b = ["6884", "8023", "9837"]

a.map.with_index { |item, index| item.push(b[index]) }
# => [["6884", true, "6884"], ["8456", false, "8023"], ["5631", false, "9837"]]
a2 = [["6884", true], ["8456", false], ["5631", false]]
a1 = ["6884", "8023", "9837"]
a2.zip(a1).map { |e2, e1| [*e2, e1] }

or, to avoid the creation of the temporary array a2.zip(a1),

a1.each_index.map { |i| [*a2[i], a1[i]] }

Both return

[["6884", true, "6884"], ["8456", false, "8023"], ["5631", false, "9837"]]

Note that neither expression mutates a2 or a1. See Array#each_index (which, without a block, returns an enumerator) and Enumerable#map.

If you want to modify the first array you can pass a block to zip to append the latter elements to the corresponding sub-array:

a = [["6884", true], ["8456", false], ["5631", false]]
b = ["6884", "8023", "9837"]

a.zip(b) { |ary, el| ary << el }

a
# => [["6884", true, "6884"], ["8456", false, "8023"], ["5631", false, "9837"]]
Related