Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 the left (-length < n < length) :

Array.prototype.rotateRight = function( n ) {   this.unshift( this.splice( n, this.length ) ); } 

Which can then be used this way:

var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; months.rotate( new Date().getMonth() ); 

My original version above has a flaw, as pointed out by Christoph in the comments bellow, a correct version is (the additional return allows chaining):

Array.prototype.rotateRight = function( n ) {   this.unshift.apply( this, this.splice( n, this.length ) );   return this; } 

Is there a more compact and/or faster solution, possibly in the context of a JavaScript framework? (none of the proposed versions bellow is either more compact or faster)

Is there any JavaScript framework out there with an array rotate built-in? (Still not answered by anyone)

like image 261
Jean Vincent Avatar asked Dec 31 '09 12:12

Jean Vincent


People also ask

How do you rotate in JavaScript?

Introduction to JavaScript rotate() canvas APIThe rotate() method allows you to rotate a drawing object on the canvas. The rotate() method accepts a rotation angle in radians. If the angle is positive, the rotation is clockwise. In case the angle is negative, the rotation is counterclockwise.

How do you shift an array in JavaScript?

shift() The shift() method removes the first element from an array and returns that removed element. This method changes the length of the array.

How do you rotate a number in JavaScript?

Initialize a variable, say X, to store the count of digits in N. Update K = (K + X) % X to reduce it to a case of left rotation. Remove the first K digits of N and append all the removed digits to the right of the digits of N. Finally, print the value of N.

How do you rotate an array to the right?

The array can be right rotated by shifting its elements to a position next to them which can be accomplished by looping through the array in reverse order (loop will start from the length of the array -1 to 0) and perform the operation arr[j] = arr[j-1].


2 Answers

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

function arrayRotate(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 🖤🧡💚💙💜

like image 145
Yukulélé Avatar answered Sep 23 '22 02:09

Yukulélé


Type-safe, generic version which mutates the array:

Array.prototype.rotate = (function() {     // save references to array functions to make lookup faster     var push = Array.prototype.push,         splice = Array.prototype.splice;      return function(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));         return this;     }; })(); 

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;      return function(count) {         var len = this.length >>> 0,             count = count >> 0;          unshift.apply(this, splice.call(this, count % len, len));         return this;     }; })(); 
like image 25
Christoph Avatar answered Sep 21 '22 02:09

Christoph