reduce array of arrays into on array in collated order
Use Array.from()
to create a new array with the length of the longest sub array. To get the length of the longest sub array, get an array of the lengths with Array.map()
and take the max item.
In the callback of Array.from()
use Array.reduceRight()
or Array.reduce()
(depending on the order you want) to collect items from each sub array. Take the item if the current index exists in the sub array. Flatten the sub arrays with Array.flat()
.
const input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
const result = Array.from(
{ length: Math.max(...input.map(o => o.length)) },
(_, i) => input.reduceRight((r, o) =>
i < o.length ? [...r, o[i]] : r
, [])
)
.flat();
console.log(result);
I made it with recursion approach to avoid mutation.
let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
function recursion(input, idx = 0) {
let tmp = input.map(elm => elm[idx])
.filter(e => e !== undefined)
return tmp[0] ? tmp.concat(recursion(input, idx + 1)) : []
}
console.log(recursion(input))
Maybe just a simple for... i
loop that checks each array for an item in position i
var input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["1st","2nd","3rd"]]
var output = []
var maxLen = Math.max(...input.map(arr => arr.length));
for (i=0; i < maxLen; i++) {
input.forEach(arr => { if (arr[i] !== undefined) output.push(arr[i]) })
}
console.log(output)
Simple, but predictable and readable
Avoiding For Each Loop
If you need to avoid forEach
, here's a similar approach where you could: get the max child array length, build a range of integers that would've been created by the for loop ([1,2,3,4]
), map each value to pivot the arrays, flatten the multi-dimensional array, and then filter out the empty cells.
First in discrete steps, and then as a one liner:
var input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["1st","2nd","3rd"]];
Multiple Steps:
var maxLen = Math.max(...input.map(arr => arr.length));
var indexes = Array(maxLen).fill().map((_,i) => i);
var pivoted = indexes.map(i => input.map(arr => arr[i] ));
var flattened = pivoted.flat().filter(el => el !== undefined);
One Liner:
var output = Array(Math.max(...input.map(arr => arr.length))).fill().map((_,i) => i)
.map(i => input.map(arr => arr[i] ))
.flat().filter(el => el !== undefined)