jayqui
jayqui

Reputation: 1899

Seeking a variation on `zip`

I have two arrays of the following shapes that I would like to combine.

arrays:

arr1 = [["apple", "aardvark"], ["banana", "beach"]]
arr2 = ['A', 'B']

desired result:

[["apple", "aardvark", "A"], ["banana", "beach", "B"]]

I'm wondering what would be an idiomatic way to do this in Ruby.

I can obviously just do a loop, such as

i = 0
while i < arr1.length
  arr1[i] << arr2[i]
  i += 1
end

But I'm wondering if there's an elegant one-liner I'm just overlooking. zip is the closest I could think of, but it's not quite there:

arr1.zip(arr2)
# => [[["apple", "aardvark"], "A"], [["banana", "beach"], "B"]]

Upvotes: 2

Views: 82

Answers (2)

Sebasti&#225;n Palma
Sebasti&#225;n Palma

Reputation: 33460

You can add each element in arr2 to arr1 according to its corresponding index using map, with_index and +:

p arr1.map.with_index { |e, i| e + [arr2[i]] }
# [["apple", "aardvark", "A"], ["banana", "beach", "B"]]

Or zipping arr1 with arr2 and mapping the sum of the elements in arr2 as an array with the elements in arr1:

p arr1.zip(arr2).map { |a, b| [*a, b] }
# [["apple", "aardvark", "A"], ["banana", "beach", "B"]]

Upvotes: 2

fphilipe
fphilipe

Reputation: 10054

Flatten each array after zipping:

arr1.zip(arr2).map(&:flatten)

Alternatively, Enumerable#zip takes an optional block, in which case it invokes the block for each combination, without returning a value though.

Thus, you could write it as follows, which is slightly less elegant:

[].tap { |res| arr1.zip(arr2) { |a, b| res.push(a + [b]) } }

Upvotes: 4

Related Questions