0

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"]]
]
2
  • In future please consider waiting longer before selecting an answer. Quick selections can discourage other answers and may result in incorrect answers going unchecked by readers. There is no rush. Many askers wait at least a couple of hours, some much longer. Just don't forget to select an answer if at least one was helpful to you. This is not a criticism of your choice here. I would have suggested the use of transpose had @Jörg not already done so. Commented Aug 3, 2020 at 17:18
  • See this explanation about formatting code on SO. See also the SO Help Center. Commented Aug 3, 2020 at 17:18

2 Answers 2

2

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

Comments

-1
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].

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.