reduce array of arrays into on array in collated orderMerge/flatten an array of arrays in JavaScript?Finding...

Does changing "sa" password require a SQL restart (in mixed mode)?

How long will my money last at roulette?

How do I write a maintainable, fast, compile-time bit-mask in C++?

Can I reorder the coordinates of a line when importing into QGIS a WKT linestring?

Automated testing of chained Queueable jobs in Salesforce

How can I portray body horror and still be sensitive to people with disabilities?

How to write painful torture scenes without being over-the-top

Can you wish for more wishes from an Efreeti bound to service via an Efreeti Bottle?

How to encourage team to refactor

Using 14 ga on part of a 20A circuit?

reduce array of arrays into on array in collated order

Failing PhD, how to go forward?

thispagestyle has no effect if no page broken(clearpage, newpage) is given

Why don't reads from /dev/zero count as I/O?

find command cannot find my files which do exist

How do I handle a blinded enemy which wants to attack someone it's sure is there?

Why Third 'Reich'? Why is 'reich' not translated when 'third' is? What is the English synonym of reich?

What dissuades people from lying about where they live in order to reduce state income taxes?

Explain an OVER clause

Badly designed reimbursement form. What does that say about the company?

What is the benefit of assigning null to some parameters in construct?

Is layered encryption more secure than long passwords?

"Happy is as happy does" What does this mean?

Define function that behaves almost identically to Mathematica function



reduce array of arrays into on array in collated order


Merge/flatten an array of arrays in JavaScript?Finding the max value of an attribute in an array of objectsHow to skip over an element in .map()?Create array of all integers between two numbers, inclusive, in Javascript/jQueryCreate ArrayList from arrayHow do I check if an array includes an object in JavaScript?How to append something to an array?How to insert an item into an array at a specific index (JavaScript)?Sort array of objects by string property valueHow do I empty an array in JavaScript?Loop through an array in JavaScriptHow to check if an object is an array?How do I remove a particular element from an array in JavaScript?For-each over an array in JavaScript?













6















I'm trying to use reduce() combine a set of arrays in a "collated" order so items with similar indexes are together. For example:



input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]

output = [ 'first','1','uno','one','second','2','dos','two','third','3','three','4' ]


It doesn't matter what order the items with similar index go as long as they are together, so a result of 'one','uno','1'... is a good as what's above. I would like to do it just using immutable variables if possible.



I have a way that works:



    const output = input.reduce((accumulator, currentArray, arrayIndex)=>{
currentArray.forEach((item,itemIndex)=>{
const newIndex = itemIndex*(arrayIndex+1);
accumulator.splice(newIndex<accumulator.length?newIndex:accumulator.length,0,item);
})
return accumulator;
})


But it's not very pretty and I don't like it, especially because of the way it mutates the accumulator in the forEach method. I feel there must be a more elegant method.



I can't believe no one has asked this before but I've tried a bunch of different queries and can't find it, so kindly tell me if it's there and I missed it. Is there a better way?



To clarify per question in comments, I would like to be able to do this without mutating any variables or arrays as I'm doing with the accumulator.splice and to only use functional methods such as .map, or .reduce not a mutating loop like a .forEach.










share|improve this question

























  • "Is there a better way?" What do you mean by "better"? "I don't like it" is not an objective coding problem. What is the requirement?

    – guest271314
    4 hours ago













  • Well for one thing I'd like to do it without mutating any variables, or introducing a .forEach loop which isn't really functional. And I think it can be done much more concisely as well. If I could zip a set of arrays together like in Python then reduce(concat) them together that way would work too.

    – jimboweb
    3 hours ago











  • I think I pretty clearly said I'd like the result to not mutate any arrays or variables, as I am doing with the accumulator.splice. That is an objective requirement.

    – jimboweb
    3 hours ago











  • Does the requirement include a restriction on using JSON.parse(JSON.stringify(input)) to avoid mutating the original array?

    – guest271314
    3 hours ago













  • Wow, lots of great answers, thanks. I'm a little torn on which one to accept as a solution, so I have to try them out. I'll choose a solution in a day or so. but I voted you all up. Thanks again.

    – jimboweb
    19 mins ago
















6















I'm trying to use reduce() combine a set of arrays in a "collated" order so items with similar indexes are together. For example:



input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]

output = [ 'first','1','uno','one','second','2','dos','two','third','3','three','4' ]


It doesn't matter what order the items with similar index go as long as they are together, so a result of 'one','uno','1'... is a good as what's above. I would like to do it just using immutable variables if possible.



I have a way that works:



    const output = input.reduce((accumulator, currentArray, arrayIndex)=>{
currentArray.forEach((item,itemIndex)=>{
const newIndex = itemIndex*(arrayIndex+1);
accumulator.splice(newIndex<accumulator.length?newIndex:accumulator.length,0,item);
})
return accumulator;
})


But it's not very pretty and I don't like it, especially because of the way it mutates the accumulator in the forEach method. I feel there must be a more elegant method.



I can't believe no one has asked this before but I've tried a bunch of different queries and can't find it, so kindly tell me if it's there and I missed it. Is there a better way?



To clarify per question in comments, I would like to be able to do this without mutating any variables or arrays as I'm doing with the accumulator.splice and to only use functional methods such as .map, or .reduce not a mutating loop like a .forEach.










share|improve this question

























  • "Is there a better way?" What do you mean by "better"? "I don't like it" is not an objective coding problem. What is the requirement?

    – guest271314
    4 hours ago













  • Well for one thing I'd like to do it without mutating any variables, or introducing a .forEach loop which isn't really functional. And I think it can be done much more concisely as well. If I could zip a set of arrays together like in Python then reduce(concat) them together that way would work too.

    – jimboweb
    3 hours ago











  • I think I pretty clearly said I'd like the result to not mutate any arrays or variables, as I am doing with the accumulator.splice. That is an objective requirement.

    – jimboweb
    3 hours ago











  • Does the requirement include a restriction on using JSON.parse(JSON.stringify(input)) to avoid mutating the original array?

    – guest271314
    3 hours ago













  • Wow, lots of great answers, thanks. I'm a little torn on which one to accept as a solution, so I have to try them out. I'll choose a solution in a day or so. but I voted you all up. Thanks again.

    – jimboweb
    19 mins ago














6












6








6


1






I'm trying to use reduce() combine a set of arrays in a "collated" order so items with similar indexes are together. For example:



input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]

output = [ 'first','1','uno','one','second','2','dos','two','third','3','three','4' ]


It doesn't matter what order the items with similar index go as long as they are together, so a result of 'one','uno','1'... is a good as what's above. I would like to do it just using immutable variables if possible.



I have a way that works:



    const output = input.reduce((accumulator, currentArray, arrayIndex)=>{
currentArray.forEach((item,itemIndex)=>{
const newIndex = itemIndex*(arrayIndex+1);
accumulator.splice(newIndex<accumulator.length?newIndex:accumulator.length,0,item);
})
return accumulator;
})


But it's not very pretty and I don't like it, especially because of the way it mutates the accumulator in the forEach method. I feel there must be a more elegant method.



I can't believe no one has asked this before but I've tried a bunch of different queries and can't find it, so kindly tell me if it's there and I missed it. Is there a better way?



To clarify per question in comments, I would like to be able to do this without mutating any variables or arrays as I'm doing with the accumulator.splice and to only use functional methods such as .map, or .reduce not a mutating loop like a .forEach.










share|improve this question
















I'm trying to use reduce() combine a set of arrays in a "collated" order so items with similar indexes are together. For example:



input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]

output = [ 'first','1','uno','one','second','2','dos','two','third','3','three','4' ]


It doesn't matter what order the items with similar index go as long as they are together, so a result of 'one','uno','1'... is a good as what's above. I would like to do it just using immutable variables if possible.



I have a way that works:



    const output = input.reduce((accumulator, currentArray, arrayIndex)=>{
currentArray.forEach((item,itemIndex)=>{
const newIndex = itemIndex*(arrayIndex+1);
accumulator.splice(newIndex<accumulator.length?newIndex:accumulator.length,0,item);
})
return accumulator;
})


But it's not very pretty and I don't like it, especially because of the way it mutates the accumulator in the forEach method. I feel there must be a more elegant method.



I can't believe no one has asked this before but I've tried a bunch of different queries and can't find it, so kindly tell me if it's there and I missed it. Is there a better way?



To clarify per question in comments, I would like to be able to do this without mutating any variables or arrays as I'm doing with the accumulator.splice and to only use functional methods such as .map, or .reduce not a mutating loop like a .forEach.







javascript arrays functional-programming






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 3 hours ago







jimboweb

















asked 4 hours ago









jimbowebjimboweb

1,74111027




1,74111027













  • "Is there a better way?" What do you mean by "better"? "I don't like it" is not an objective coding problem. What is the requirement?

    – guest271314
    4 hours ago













  • Well for one thing I'd like to do it without mutating any variables, or introducing a .forEach loop which isn't really functional. And I think it can be done much more concisely as well. If I could zip a set of arrays together like in Python then reduce(concat) them together that way would work too.

    – jimboweb
    3 hours ago











  • I think I pretty clearly said I'd like the result to not mutate any arrays or variables, as I am doing with the accumulator.splice. That is an objective requirement.

    – jimboweb
    3 hours ago











  • Does the requirement include a restriction on using JSON.parse(JSON.stringify(input)) to avoid mutating the original array?

    – guest271314
    3 hours ago













  • Wow, lots of great answers, thanks. I'm a little torn on which one to accept as a solution, so I have to try them out. I'll choose a solution in a day or so. but I voted you all up. Thanks again.

    – jimboweb
    19 mins ago



















  • "Is there a better way?" What do you mean by "better"? "I don't like it" is not an objective coding problem. What is the requirement?

    – guest271314
    4 hours ago













  • Well for one thing I'd like to do it without mutating any variables, or introducing a .forEach loop which isn't really functional. And I think it can be done much more concisely as well. If I could zip a set of arrays together like in Python then reduce(concat) them together that way would work too.

    – jimboweb
    3 hours ago











  • I think I pretty clearly said I'd like the result to not mutate any arrays or variables, as I am doing with the accumulator.splice. That is an objective requirement.

    – jimboweb
    3 hours ago











  • Does the requirement include a restriction on using JSON.parse(JSON.stringify(input)) to avoid mutating the original array?

    – guest271314
    3 hours ago













  • Wow, lots of great answers, thanks. I'm a little torn on which one to accept as a solution, so I have to try them out. I'll choose a solution in a day or so. but I voted you all up. Thanks again.

    – jimboweb
    19 mins ago

















"Is there a better way?" What do you mean by "better"? "I don't like it" is not an objective coding problem. What is the requirement?

– guest271314
4 hours ago







"Is there a better way?" What do you mean by "better"? "I don't like it" is not an objective coding problem. What is the requirement?

– guest271314
4 hours ago















Well for one thing I'd like to do it without mutating any variables, or introducing a .forEach loop which isn't really functional. And I think it can be done much more concisely as well. If I could zip a set of arrays together like in Python then reduce(concat) them together that way would work too.

– jimboweb
3 hours ago





Well for one thing I'd like to do it without mutating any variables, or introducing a .forEach loop which isn't really functional. And I think it can be done much more concisely as well. If I could zip a set of arrays together like in Python then reduce(concat) them together that way would work too.

– jimboweb
3 hours ago













I think I pretty clearly said I'd like the result to not mutate any arrays or variables, as I am doing with the accumulator.splice. That is an objective requirement.

– jimboweb
3 hours ago





I think I pretty clearly said I'd like the result to not mutate any arrays or variables, as I am doing with the accumulator.splice. That is an objective requirement.

– jimboweb
3 hours ago













Does the requirement include a restriction on using JSON.parse(JSON.stringify(input)) to avoid mutating the original array?

– guest271314
3 hours ago







Does the requirement include a restriction on using JSON.parse(JSON.stringify(input)) to avoid mutating the original array?

– guest271314
3 hours ago















Wow, lots of great answers, thanks. I'm a little torn on which one to accept as a solution, so I have to try them out. I'll choose a solution in a day or so. but I voted you all up. Thanks again.

– jimboweb
19 mins ago





Wow, lots of great answers, thanks. I'm a little torn on which one to accept as a solution, so I have to try them out. I'll choose a solution in a day or so. but I voted you all up. Thanks again.

– jimboweb
19 mins ago












4 Answers
4






active

oldest

votes


















4














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)





share|improve this answer

































    3














    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.



    Then collect the non undefined items at the current index from each sub array with Array.reduceRight() or Array.reduce() (depending on the order you want), and use Array.flat() to get a single array.






    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) => o[i] === undefined ? r : [...r, o[i]], []))
    .flat();

    console.log(result);








    share|improve this answer


























    • Cool! I like it!

      – KyleMit
      2 hours ago











    • -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

      – guest271314
      2 hours ago



















    2














    Funny solution




    1. add index as prefix on inner array

    2. Flatten the array

    3. sort the array

    4. Remove the prefix





    let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
    let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
    console.log(ranked.flat().sort().map(i=>i.split('---')[1]));








    share|improve this answer


























    • Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

      – jimboweb
      10 mins ago






    • 1





      yes this is bit messy , i admit it

      – sumit
      8 mins ago



















    2














    Here I have provided a generator function that will yield the values in the desired order. You could easily turn this into a regular function returning an array if you replace the yield with a push to a results array to be returned.



    The algorithm takes in all the arrays as arguments, then gets the iterators for each of them. Then it enters the main loop where it treats the iters array like a queue, taking the iterator in front, yielding the next generated value, then placing it back at the end of the queue unless it is empty. The efficiency would improve if you transformed the array into a linked list where adding to the front and back take constant time, whereas a shift on an array is linear time to shift everything down one spot.



    function* collate(...arrays) {
    const iters = arrays.map(a => a.values());
    while(iters.length > 0) {
    const iter = iters.shift();
    const {done, value} = iter.next();
    if(done) continue;
    yield value;
    iters.push(iter);
    }
    }





    share|improve this answer
























    • This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

      – jimboweb
      7 mins ago











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54796607%2freduce-array-of-arrays-into-on-array-in-collated-order%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4














    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)





    share|improve this answer






























      4














      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)





      share|improve this answer




























        4












        4








        4







        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)





        share|improve this answer















        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)





        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)





        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)






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 31 mins ago

























        answered 3 hours ago









        KyleMitKyleMit

        58.6k35241401




        58.6k35241401

























            3














            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.



            Then collect the non undefined items at the current index from each sub array with Array.reduceRight() or Array.reduce() (depending on the order you want), and use Array.flat() to get a single array.






            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) => o[i] === undefined ? r : [...r, o[i]], []))
            .flat();

            console.log(result);








            share|improve this answer


























            • Cool! I like it!

              – KyleMit
              2 hours ago











            • -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

              – guest271314
              2 hours ago
















            3














            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.



            Then collect the non undefined items at the current index from each sub array with Array.reduceRight() or Array.reduce() (depending on the order you want), and use Array.flat() to get a single array.






            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) => o[i] === undefined ? r : [...r, o[i]], []))
            .flat();

            console.log(result);








            share|improve this answer


























            • Cool! I like it!

              – KyleMit
              2 hours ago











            • -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

              – guest271314
              2 hours ago














            3












            3








            3







            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.



            Then collect the non undefined items at the current index from each sub array with Array.reduceRight() or Array.reduce() (depending on the order you want), and use Array.flat() to get a single array.






            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) => o[i] === undefined ? r : [...r, o[i]], []))
            .flat();

            console.log(result);








            share|improve this answer















            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.



            Then collect the non undefined items at the current index from each sub array with Array.reduceRight() or Array.reduce() (depending on the order you want), and use Array.flat() to get a single array.






            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) => o[i] === undefined ? r : [...r, o[i]], []))
            .flat();

            console.log(result);








            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) => o[i] === undefined ? r : [...r, o[i]], []))
            .flat();

            console.log(result);





            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) => o[i] === undefined ? r : [...r, o[i]], []))
            .flat();

            console.log(result);






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 3 hours ago

























            answered 4 hours ago









            Ori DroriOri Drori

            77.8k138492




            77.8k138492













            • Cool! I like it!

              – KyleMit
              2 hours ago











            • -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

              – guest271314
              2 hours ago



















            • Cool! I like it!

              – KyleMit
              2 hours ago











            • -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

              – guest271314
              2 hours ago

















            Cool! I like it!

            – KyleMit
            2 hours ago





            Cool! I like it!

            – KyleMit
            2 hours ago













            -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

            – guest271314
            2 hours ago





            -4 bytes [...Array(Math.max(...input.map(o => o.length)))].map((_,i)=>{})

            – guest271314
            2 hours ago











            2














            Funny solution




            1. add index as prefix on inner array

            2. Flatten the array

            3. sort the array

            4. Remove the prefix





            let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
            let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
            console.log(ranked.flat().sort().map(i=>i.split('---')[1]));








            share|improve this answer


























            • Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

              – jimboweb
              10 mins ago






            • 1





              yes this is bit messy , i admit it

              – sumit
              8 mins ago
















            2














            Funny solution




            1. add index as prefix on inner array

            2. Flatten the array

            3. sort the array

            4. Remove the prefix





            let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
            let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
            console.log(ranked.flat().sort().map(i=>i.split('---')[1]));








            share|improve this answer


























            • Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

              – jimboweb
              10 mins ago






            • 1





              yes this is bit messy , i admit it

              – sumit
              8 mins ago














            2












            2








            2







            Funny solution




            1. add index as prefix on inner array

            2. Flatten the array

            3. sort the array

            4. Remove the prefix





            let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
            let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
            console.log(ranked.flat().sort().map(i=>i.split('---')[1]));








            share|improve this answer















            Funny solution




            1. add index as prefix on inner array

            2. Flatten the array

            3. sort the array

            4. Remove the prefix





            let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
            let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
            console.log(ranked.flat().sort().map(i=>i.split('---')[1]));








            let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
            let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
            console.log(ranked.flat().sort().map(i=>i.split('---')[1]));





            let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
            let ranked=input.map(i=>i.map((j,k)=>k+'---'+j)).slice()
            console.log(ranked.flat().sort().map(i=>i.split('---')[1]));






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 2 hours ago

























            answered 3 hours ago









            sumitsumit

            8,18993479




            8,18993479













            • Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

              – jimboweb
              10 mins ago






            • 1





              yes this is bit messy , i admit it

              – sumit
              8 mins ago



















            • Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

              – jimboweb
              10 mins ago






            • 1





              yes this is bit messy , i admit it

              – sumit
              8 mins ago

















            Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

            – jimboweb
            10 mins ago





            Clever answer. I did consider doing something like this. I was thinking of something more like making the inner map return something like {ind:k,val:j} followed by a .sort((a,b)=>return a.ind-b.ind) but it's the same idea. I decided against it because creating unnecessary objects (or strings) felt like doing unnecessary work. But still a good answer, thanks.

            – jimboweb
            10 mins ago




            1




            1





            yes this is bit messy , i admit it

            – sumit
            8 mins ago





            yes this is bit messy , i admit it

            – sumit
            8 mins ago











            2














            Here I have provided a generator function that will yield the values in the desired order. You could easily turn this into a regular function returning an array if you replace the yield with a push to a results array to be returned.



            The algorithm takes in all the arrays as arguments, then gets the iterators for each of them. Then it enters the main loop where it treats the iters array like a queue, taking the iterator in front, yielding the next generated value, then placing it back at the end of the queue unless it is empty. The efficiency would improve if you transformed the array into a linked list where adding to the front and back take constant time, whereas a shift on an array is linear time to shift everything down one spot.



            function* collate(...arrays) {
            const iters = arrays.map(a => a.values());
            while(iters.length > 0) {
            const iter = iters.shift();
            const {done, value} = iter.next();
            if(done) continue;
            yield value;
            iters.push(iter);
            }
            }





            share|improve this answer
























            • This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

              – jimboweb
              7 mins ago
















            2














            Here I have provided a generator function that will yield the values in the desired order. You could easily turn this into a regular function returning an array if you replace the yield with a push to a results array to be returned.



            The algorithm takes in all the arrays as arguments, then gets the iterators for each of them. Then it enters the main loop where it treats the iters array like a queue, taking the iterator in front, yielding the next generated value, then placing it back at the end of the queue unless it is empty. The efficiency would improve if you transformed the array into a linked list where adding to the front and back take constant time, whereas a shift on an array is linear time to shift everything down one spot.



            function* collate(...arrays) {
            const iters = arrays.map(a => a.values());
            while(iters.length > 0) {
            const iter = iters.shift();
            const {done, value} = iter.next();
            if(done) continue;
            yield value;
            iters.push(iter);
            }
            }





            share|improve this answer
























            • This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

              – jimboweb
              7 mins ago














            2












            2








            2







            Here I have provided a generator function that will yield the values in the desired order. You could easily turn this into a regular function returning an array if you replace the yield with a push to a results array to be returned.



            The algorithm takes in all the arrays as arguments, then gets the iterators for each of them. Then it enters the main loop where it treats the iters array like a queue, taking the iterator in front, yielding the next generated value, then placing it back at the end of the queue unless it is empty. The efficiency would improve if you transformed the array into a linked list where adding to the front and back take constant time, whereas a shift on an array is linear time to shift everything down one spot.



            function* collate(...arrays) {
            const iters = arrays.map(a => a.values());
            while(iters.length > 0) {
            const iter = iters.shift();
            const {done, value} = iter.next();
            if(done) continue;
            yield value;
            iters.push(iter);
            }
            }





            share|improve this answer













            Here I have provided a generator function that will yield the values in the desired order. You could easily turn this into a regular function returning an array if you replace the yield with a push to a results array to be returned.



            The algorithm takes in all the arrays as arguments, then gets the iterators for each of them. Then it enters the main loop where it treats the iters array like a queue, taking the iterator in front, yielding the next generated value, then placing it back at the end of the queue unless it is empty. The efficiency would improve if you transformed the array into a linked list where adding to the front and back take constant time, whereas a shift on an array is linear time to shift everything down one spot.



            function* collate(...arrays) {
            const iters = arrays.map(a => a.values());
            while(iters.length > 0) {
            const iter = iters.shift();
            const {done, value} = iter.next();
            if(done) continue;
            yield value;
            iters.push(iter);
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 2 hours ago









            kamoroso94kamoroso94

            1,38511316




            1,38511316













            • This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

              – jimboweb
              7 mins ago



















            • This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

              – jimboweb
              7 mins ago

















            This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

            – jimboweb
            7 mins ago





            This is a great answer, thanks. But the while loop felt kind of like the .forEach I was trying to get around. But it's still a good answer so I voted it up.

            – jimboweb
            7 mins ago


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54796607%2freduce-array-of-arrays-into-on-array-in-collated-order%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            ORA-01691 (unable to extend lob segment) even though my tablespace has AUTOEXTEND onORA-01692: unable to...

            Always On Availability groups resolving state after failover - Remote harden of transaction...

            Circunscripción electoral de Guipúzcoa Referencias Menú de navegaciónLas claves del sistema electoral en...