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)
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.
shift() The shift() method removes the first element from an array and returns that removed element. This method changes the length of the array.
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.
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].
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 🖤🧡💚💙💜
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; }; })();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With