Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interleave array elements

Tags:

javascript

What is a fast and simple implementation of interleave:

console.log( interleave([1,2,3,4,5,6]      ,2) ); // [1,4,2,5,3,6]
console.log( interleave([1,2,3,4,5,6,7,8]  ,2) ); // [1,5,2,6,3,7,4,8]
console.log( interleave([1,2,3,4,5,6]      ,3) ); // [1,3,5,2,4,6]
console.log( interleave([1,2,3,4,5,6,7,8,9],3) ); // [1,4,7,2,5,8,3,6,9]

This mimics taking the array and splitting it into n equal parts, and then shifting items off the front of each partial array in sequence. (n=2 simulates a perfect halving and single shuffle of a deck of cards.)

I don't much care exactly what happens when the number of items in the array is not evenly divisible by n. Reasonable answers might either interleave the leftovers, or even "punt" and throw them all onto the end.

like image 236
Phrogz Avatar asked Feb 21 '23 09:02

Phrogz


1 Answers

function interleave( deck, step ) {
    var copyDeck = deck.slice(),
        stop = Math.floor(copyDeck.length/step),
        newDeck = [];    
    for (var i=0; i<step; i++) {
        for (var j=0; j<stop; j++) {
            newDeck[i + (j*step)] = copyDeck.shift();
        }        
    }
    if(copyDeck.length>0) {
        newDeck = newDeck.concat(copyDeck);
    }
    return newDeck;
}

It could be done with a counter instead of shift()

function interleave( deck, step ) {
    var len = deck.length,
        stop = Math.floor(len/step),
        newDeck = [],
        cnt=0;
    for (var i=0; i<step; i++) {
        for (var j=0; j<stop; j++) {
            newDeck[i + (j*step)] = deck[cnt++];
        }        
    }
    if(cnt<len) {
        newDeck = newDeck.concat(deck.slice(cnt,len));
    }
    return newDeck;
}

And instead of appending the extras to the end, we can use ceil and exit when we run out

function interleave( deck, step ) {
    var copyDeck = deck.slice(),
        stop = Math.ceil(copyDeck.length/step),
        newDeck = [];    
    for (var i=0; i<step; i++) {
        for (var j=0; j<stop && copyDeck.length>0; j++) {
            newDeck[i + (j*step)] = copyDeck.shift();
        }        
    }
    return newDeck;
}
like image 81
epascarello Avatar answered Mar 05 '23 19:03

epascarello