Eleventy
Eleventy

Reputation: 23

Create new arrays from nested arrays based on corresponding indexes

I have an array of nested arrays, I need to create new arrays made up of the elements in corresponding index positions. Kind of hard to explain but here is what I'm starting with and what I need to produce:

arrays = [ 
  [["ab", "cd", "ef", "gh"], ["ik", "lm", "no", "pq"],
   ["rs", "tu", "vw", "xy"]],
  [["z1", "23", "45", "67"],["89", "AB", "CD", "EF"],["GH", "IJ", "KL", "MN"]]
]

goal = [
  [["ab", "ik", "rs"], ["cd", "lm", "tu"], ["ef", "no", "vw"], ["gh", "pq", "xy"]],
  [["z1", "89", "GH"], ["23", "AB", "IJ"], ["45", "CD", "KL"], ["67", "EF", "MN"]]
]

Upvotes: 0

Views: 80

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110685

arrays.map { |a,*b| a.zip(*b) }
  #=> [
  #     [["ab", "ik", "rs"], ["cd", "lm", "tu"], ["ef", "no", "vw"],
  #      ["gh", "pq", "xy"]],
  #     [["z1", "89", "GH"], ["23", "AB", "IJ"], ["45", "CD", "KL"],
  #      ["67", "EF", "MN"]]
  #   ] 

This makes use of what is called Array decomposition. arrays has two elements. When the first is passed to the block the block variables a and b are assigned values as follows:

a, *b = arrays[0]
  #=> [["ab", "cd", "ef", "gh"], ["ik", "lm", "no", "pq"],
  #    ["rs", "tu", "vw", "xy"]] 

We see that

a #=> ["ab", "cd", "ef", "gh"] 
b #=> [["ik", "lm", "no", "pq"], ["rs", "tu", "vw", "xy"]] 

Here is a good explanation of how Ruby's splat operator (*) works. Using array decomposition and the splat operator in combination is a powerful tool that every Rubyist needs to master.

Whenever Array#transpose can be used Array#zip can be used instead. The reverse is true if each element of the array has the same number of elements. Since we are mapping, the latter requirement applies separately to array[0] and array[1].

Upvotes: -1

Jörg W Mittag
Jörg W Mittag

Reputation: 369478

You are simply transposing the inner arrays:

arrays.map(&:transpose)
#=> [
#     [
#       ["ab", "ik", "rs"], 
#       ["cd", "lm", "tu"], 
#       ["ef", "no", "vw"], 
#       ["gh", "pq", "xy"]
#     ], 
#     [
#       ["z1", "89", "GH"], 
#       ["23", "AB", "IJ"], 
#       ["45", "CD", "KL"], 
#       ["67", "EF", "MN"]
#     ]
#   ]

Upvotes: 2

Related Questions