Rotate the elements in an array in JavaScript

后端 未结 30 1787
走了就别回头了
走了就别回头了 2020-11-22 10:55

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

30条回答
  •  被撕碎了的回忆
    2020-11-22 11:10

    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;

    1. There is no need for a conditional for positive or negative input since it reveals a violation of DRY .you could do this with one map because every negative n has a positive equivalent (Totally right..)
    2. An Array function should either change the current array or make a new array, your function could do either depending on whether a shift is necessary or not (Totally right..)

    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;
    };
    

提交回复
热议问题