Skip to content Skip to sidebar Skip to footer

Rotate The Elements In An Array In Javascript

I was wondering what was the most efficient way to rotate a JavaScript array. I came up with this solution, where a positive n rotates the array to the right, and a negative n to t

Solution 1:

You can use push(), pop(), shift() and unshift() methods:

functionarrayRotate(arr, reverse) {
  if (reverse) arr.unshift(arr.pop());
  else arr.push(arr.shift());
  return arr;
}

usage:

arrayRotate([1, 2, 3, 4, 5]);       // [2, 3, 4, 5, 1];arrayRotate([1, 2, 3, 4, 5], true); // [5, 1, 2, 3, 4];

If you need count argument see my other answer: https://stackoverflow.com/a/33451102 πŸ–€πŸ§‘πŸ’šπŸ’™πŸ’œ

Solution 2:

Type-safe, generic version which mutates the array:

Array.prototype.rotate = (function() {
    // save references to array functions to make lookup fastervar push = Array.prototype.push,
        splice = Array.prototype.splice;

    returnfunction(count) {
        var len = this.length >>> 0, // convert to uint
            count = count >> 0; // convert to int// convert count to value in range [0, len)
        count = ((count % len) + len) % len;

        // use splice.call() instead of this.splice() to make function generic
        push.apply(this, splice.call(this, 0, count));
        returnthis;
    };
})();

In the comments, Jean raised the issue that the code doesn't support overloading of push() and splice(). I don't think this is really useful (see comments), but a quick solution (somewhat of a hack, though) would be to replace the line

push.apply(this, splice.call(this, 0, count));

with this one:

(this.push || push).apply(this, (this.splice || splice).call(this, 0, count));

Using unshift() instead of push() is nearly twice as fast in Opera 10, whereas the differences in FF were negligible; the code:

Array.prototype.rotate = (function() {
    var unshift = Array.prototype.unshift,
        splice = Array.prototype.splice;

    returnfunction(count) {
        var len = this.length >>> 0,
            count = count >> 0;

        unshift.apply(this, splice.call(this, count % len, len));
        returnthis;
    };
})();

Solution 3:

I would probably do something like this:

Array.prototype.rotate = function(n) {
    n = n % this.length;
    returnthis.slice(n, this.length).concat(this.slice(0, n));
}

Edit    Here’s a mutator version:

Array.prototype.rotate = function(n) {
    n = n % this.length;
    while (this.length && n < 0) n += this.length;
    this.push.apply(this, this.splice(0, n));
    returnthis;
}

Solution 4:

This function works in both way and works with any number (even with number greater than array length):

function arrayRotate(arr, count){
  count -= arr.length * Math.floor(count / arr.length);
  arr.push.apply(arr, arr.splice(0, count));
  return arr;
}

usage:

for(let i = -6 ; i <= 6 ; i++) {
  console.log(arrayRotate(["🧑","πŸ’š","πŸ’™","πŸ’œ","πŸ–€"], i), i);
}

result:

[ "πŸ–€", "🧑", "πŸ’š", "πŸ’™", "πŸ’œ" ]    -6[ "🧑", "πŸ’š", "πŸ’™", "πŸ’œ", "πŸ–€" ]    -5[ "πŸ’š", "πŸ’™", "πŸ’œ", "πŸ–€", "🧑" ]    -4[ "πŸ’™", "πŸ’œ", "πŸ–€", "🧑", "πŸ’š" ]    -3[ "πŸ’œ", "πŸ–€", "🧑", "πŸ’š", "πŸ’™" ]    -2[ "πŸ–€", "🧑", "πŸ’š", "πŸ’™", "πŸ’œ" ]    -1[ "🧑", "πŸ’š", "πŸ’™", "πŸ’œ", "πŸ–€" ]0[ "πŸ’š", "πŸ’™", "πŸ’œ", "πŸ–€", "🧑" ]1[ "πŸ’™", "πŸ’œ", "πŸ–€", "🧑", "πŸ’š" ]2[ "πŸ’œ", "πŸ–€", "🧑", "πŸ’š", "πŸ’™" ]3[ "πŸ–€", "🧑", "πŸ’š", "πŸ’™", "πŸ’œ" ]4[ "🧑", "πŸ’š", "πŸ’™", "πŸ’œ", "πŸ–€" ]5[ "πŸ’š", "πŸ’™", "πŸ’œ", "πŸ–€", "🧑" ]6

Solution 5:

So many of these answers seem over-complicated and difficult to read. I don't think I saw anyone using splice with concat...

functionrotateCalendar(){
    var cal=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
    cal=cal.concat(cal.splice(0,newDate().getMonth()));
    console.log(cal);  // return cal;
}

console.log outputs (*generated in May):

["May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr"]

As for compactness, I can offer a couple of generic one-liner functions (not counting the console.log | return portion). Just feed it the array and the target value in the arguments.

I combine these functions into one for a four-player card game program where the array is ['N','E','S','W']. I left them separate in case anyone wants to copy/paste for their needs. For my purposes, I use the functions when seeking whose turn is next to play/act during different phases of the game (Pinochle). I haven't bothered testing for speed, so if someone else wants to, feel free to let me know the results.

*notice, the only difference between functions is the "+1".

functionrotateToFirst(arr,val){  // val is Trump Declarer's seat, first to play
    arr=arr.concat(arr.splice(0,arr.indexOf(val)));
    console.log(arr); // return arr;
}
functionrotateToLast(arr,val){  // val is Dealer's seat, last to bid
    arr=arr.concat(arr.splice(0,arr.indexOf(val)+1));
    console.log(arr); // return arr;
}

combination function...

function rotateArray(arr,val,pos){
    // set pos to 0 if moving val to first position, or 1 for last position
    arr=arr.concat(arr.splice(0,arr.indexOf(val)+pos));
    return arr;
}
var adjustedArray=rotateArray(['N','E','S','W'],'S',1);

adjustedArray=

W,N,E,S

Post a Comment for "Rotate The Elements In An Array In Javascript"