2

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?

0

4 Answers 4

6

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"]]
Sign up to request clarification or add additional context in comments.

1 Comment

Only note is that this could be consumptive on a larger data set as it creates N * N + 2 new Arrays where N = a.size
5

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

2 Comments

This also works well, I just prefer the cleanliness of Mehmet's answer. Thank you!
It should be noted that this mutates a.
3
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.

1 Comment

I understood where you were going. Iterative methods, especially ones that take a block, can be confusing in ruby because some return immediately and others return Enumerators. zip's block is extra confusing since it yields the zipped elements but always returns nil.
2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.