JavaScript数组rotate()

Jea*_*ent 65 javascript arrays rotation

我想知道旋转JavaScript数组的最有效方法是什么.

我想出了这个解决方案,其中正向n旋转数组向右旋转,负向左旋转n(-length < n < length):

Array.prototype.rotateRight = function( n ) {
  this.unshift( this.splice( n, this.length ) )
}
Run Code Online (Sandbox Code Playgroud)

然后可以这样使用:

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

我上面的原始版本有一个缺陷,正如Christoph在下面的评论中指出的那样,正确的版本是(额外的返回允许链接):

Array.prototype.rotateRight = function( n ) {
  this.unshift.apply( this, this.splice( n, this.length ) )
  return this;
}
Run Code Online (Sandbox Code Playgroud)

是否有更紧凑和/或更快的解决方案,可能在JavaScript框架的上下文中?(以下提出的版本都没有更紧凑或更快)

是否有任何JavaScript框架,内置数组旋转?(还没有人回答)

Yuk*_*élé 124

您可以使用push(),pop(),shift()unshift()功能:

function arrayRotate(arr, reverse) {
  if (reverse) arr.unshift(arr.pop());
  else arr.push(arr.shift());
  return arr;
}
Run Code Online (Sandbox Code Playgroud)

用法:

arrayRotate(['h','e','l','l','o']);       // ['e','l','l','o','h'];
arrayRotate(['h','e','l','l','o'], true); // ['o','h','e','l','l'];
Run Code Online (Sandbox Code Playgroud)

如果您需要count参数,请参阅我的其他答案:https://stackoverflow.com/a/33451102

  • 请注意:请注意,此方法具有侵入性,它会操作作为参数发送的数组。不难解决[发送前复制数组](http://stackoverflow.com/questions/3978492/javascript-fastest-way-to-duplicate-an-array-slice-vs-for-loop) (3认同)

Chr*_*oph 49

改变数组的类型安全的通用版本:

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;
    };
})();
Run Code Online (Sandbox Code Playgroud)

在评论中,Jean提出了代码不支持push()和重载的问题splice().我认为这不是很有用(见评论),但快速解决方案(虽然有点黑客)将取代线

push.apply(this, splice.call(this, 0, count));
Run Code Online (Sandbox Code Playgroud)

这一个:

(this.push || push).apply(this, (this.splice || splice).call(this, 0, count));
Run Code Online (Sandbox Code Playgroud)

使用unshift()而不是push()几乎是Opera 10的两倍,而FF的差异可以忽略不计; 代码:

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;
    };
})();
Run Code Online (Sandbox Code Playgroud)

  • 很好的缓存`Array.prototype`方法!+1 (2认同)

Gum*_*mbo 32

我可能会这样做:

Array.prototype.rotate = function(n) {
    return this.slice(n, this.length).concat(this.slice(0, n));
}
Run Code Online (Sandbox Code Playgroud)

编辑     这里是一个mutator版本:

Array.prototype.rotate = function(n) {
    while (this.length && n < 0) n += this.length;
    this.push.apply(this, this.splice(0, n));
    return this;
}
Run Code Online (Sandbox Code Playgroud)

  • 我在 return 语句之前添加了 `n = n % this.length` 以处理负数和/或超出边界的数字。 (2认同)

Yuk*_*élé 19

此函数以两种方式工作,并适用于任何数字(即使数字大于数组长度):

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

例:

for(let i = -6 ; i <= 6 ; i++) {
  console.log(arrayRotate(["","","","",""], i), i);
}
Run Code Online (Sandbox Code Playgroud)

结果:

[ "", "", "", "", "" ]    -6
[ "", "", "", "", "" ]    -5
[ "", "", "", "", "" ]    -4
[ "", "", "", "", "" ]    -3
[ "", "", "", "", "" ]    -2
[ "", "", "", "", "" ]    -1
[ "", "", "", "", "" ]    0
[ "", "", "", "", "" ]    1
[ "", "", "", "", "" ]    2
[ "", "", "", "", "" ]    3
[ "", "", "", "", "" ]    4
[ "", "", "", "", "" ]    5
[ "", "", "", "", "" ]    6
Run Code Online (Sandbox Code Playgroud)

  • @ognockocaten这不是问题,而是这个函数的工作原理。如果你想保持原始数组不变,请在之前克隆它:`var arr2 = arrayRotate(arr.slice(0), 5)` (3认同)

Dud*_*aig 9

使用 ES6 的扩展作为不可变示例......

[...array.slice(1, array.length), array[0]]
Run Code Online (Sandbox Code Playgroud)

[array[array.items.length -1], ...array.slice(0, array.length -1)]
Run Code Online (Sandbox Code Playgroud)

虽然它可能不是最有效的,但它很简洁。


kas*_*ndr 9

切片和解构的简单解决方案:

const rotate = (arr, count = 1) => {
  return [...arr.slice(count, arr.length), ...arr.slice(0, count)];
};

const arr = [1,2,3,4,5];

console.log(rotate(arr, 1));  // [2, 3, 4, 5, 1]
console.log(rotate(arr, 2));  // [3, 4, 5, 1, 2]
console.log(rotate(arr, -2)); // [4, 5, 1, 2, 3]
console.log(rotate(arr, -1)); // [5, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

  • 这真是太好了!您可以通过设置默认值来避免检查“count === 0”。这将允许你将其变成单行: `constrotate = (arr, n = 1) =&gt; [...arr.slice(n, arr.length), ...arr.slice(0, n )];` (3认同)

小智 6

这是一种移动数组中项目的非常简单的方法:

function rotate(array, stepsToShift) {

    for (var i = 0; i < stepsToShift; i++) {
        array.unshift(array.pop());
    }

    return array;
}
Run Code Online (Sandbox Code Playgroud)


mic*_*usa 5

这些答案中有很多看起来过于复杂且难以阅读.我不认为我看到有人使用拼接连接...

function rotateCalendar(){
    var cal=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
    cal=cal.concat(cal.splice(0,new Date().getMonth()));
    console.log(cal);  // return cal;
}
Run Code Online (Sandbox Code Playgroud)

console.log输出(*在5月生成):

["May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr"]
Run Code Online (Sandbox Code Playgroud)

至于紧凑性,我可以提供一些通用的单行功能(不包括console.log |返回部分).只需在参数中输入数组和目标值即可.

我将这些功能组合成一个四人卡片游戏程序,其中数组是['N','E','S','W'].如果有人想要复制/粘贴他们的需求,我会将它们分开.为了我的目的,我在游戏的不同阶段(Pinochle)寻找轮到接下来的比赛时使用这些功能.我没有考虑速度测试,所以如果有其他人愿意,请随时告诉我结果.

*注意,功能之间的唯一区别是"+1".

function rotateToFirst(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;
}
function rotateToLast(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;
}
Run Code Online (Sandbox Code Playgroud)

组合功能......

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);
Run Code Online (Sandbox Code Playgroud)

adjustedArray =

W,N,E,S
Run Code Online (Sandbox Code Playgroud)