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
The accepted answer has a flaw of not being able to handle arrays larger than the call stack size which depends on the session but should be around like 100~300K items. For instance, in the current Chrome session that i tried it was 250891. In many cases you may not even know to what size the array might dynamically grow into. So that's a serious problem.
To overcome this limitation, I guess one interesting method is utilizing Array.prototype.map() and mapping the elements by rearranging the indices in a circular fashion. This method takes one integer argument. If this argument is positive it will rotate on increasing indices and if negative on decreasing indices direction. This has only O(n) time complexity and will return a new array without mutating the one it's called upon while handling millions of items without any problem. Let see how it works;
Array.prototype.rotate = function(n) {
var len = this.length;
return !(n % len) ? this
: n > 0 ? this.map((e,i,a) => a[(i + n) % len])
: this.map((e,i,a) => a[(len - (len - i - n) % len) % len]);
};
var a = [1,2,3,4,5,6,7,8,9],
b = a.rotate(2);
console.log(JSON.stringify(b));
b = a.rotate(-1);
console.log(JSON.stringify(b));
Actually after i have been criticized on two matters as follows;
I have decided to modify the code as follows;
Array.prototype.rotate = function(n) {
var len = this.length;
return !(n % len) ? this.slice()
: this.map((e,i,a) => a[(i + (len + n % len)) % len]);
};
var a = [1,2,3,4,5,6,7,8,9],
b = a.rotate(10);
console.log(JSON.stringify(b));
b = a.rotate(-10);
console.log(JSON.stringify(b));
Then again; of course the JS functors like Array.prototype.map() are slow compared to their equivalents coded in plain JS. In order to gain more than 100% performance boost the following would probably be my choice of Array.prototype.rotate() if i ever need to rotate an array in production code like the one i used in my attempt on String.prototype.diff()
Array.prototype.rotate = function(n){
var len = this.length,
res = new Array(this.length);
if (n % len === 0) return this.slice();
else for (var i = 0; i < len; i++) res[i] = this[(i + (len + n % len)) % len];
return res;
};