Reputation: 23
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
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
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