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)

136834 次浏览

我可能会这样做:

Array.prototype.rotate = function(n) {
n = n % this.length;
return this.slice(n, this.length).concat(this.slice(0, n));
}

编辑 这里有一个变异者版本:

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

如何递增一个计数器,然后得到除以数组长度的余数,得到你应该在的位置。

var i = 0;
while (true);
{
var position = i % months.length;
alert(months[position]);
++i;
}

除此之外,语言语法应该可以正常工作。

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

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

在评论中,Jean 提出了代码不支持 push()splice()过载的问题。我不认为这是真正有用的(见注释) ,但一个快速的解决方案(虽然有点黑客)将是替换行

push.apply(this, splice.call(this, 0, count));

with this one:

(this.push || push).apply(this, (this.splice || splice).call(this, 0, count));

使用 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;
};
})();

如果你的数组很大并且/或者你要旋转很多次,你可以考虑使用链表来代替数组。

When I couldn't find a ready-made snippet to start a list of days with 'today', I did it like this (not quite generic, probably far less refined than the above examples, but did the job):

//returns 7 day names with today first
function startday() {
const days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
let today = new Date();
let start = today.getDay(); //gets day number
if (start == 0) { //if Sunday, days are in order
return days
}
else { //if not Sunday, start days with today
return days.slice(start).concat(days.slice(0,start))
}
}

由于一个比我更好的程序员的一点重构,它比我最初的尝试短了一两行,但是欢迎任何关于效率的进一步评论。

@ Christoph 你的代码很干净,但是 最慢的60% 比我找到的这个要好。看看 jsPerf 上的结果: < a href = “ http://jsPerf.com/js-rol-array/2”rel = “ nofollow”> http://jsPerf.com/js-rotate-array/2 [编辑]好了,现在有更多的浏览器,不明显的巫术方法是最好的

var rotateArray = function(a, inc) {
for (var l = a.length, inc = (Math.abs(inc) >= l && (inc %= l), inc < 0 && (inc += l), inc), i, x; inc; inc = (Math.ceil(l / inc) - 1) * inc - l + (l = inc))
for (i = l; i > inc; x = a[--i], a[i] = a[i - inc], a[i - inc] = x);
return a;
};


var array = ['a','b','c','d','e','f','g','h','i'];


console.log(array);
console.log(rotateArray(array.slice(), -1)); // Clone array with slice() to keep original

@ molokoloco 我需要一个函数,我可以配置旋转的方向-真为前进和假为后退。我创建了一个代码片段,该代码片段接受一个方向、一个计数器和一个数组,并输出一个对象,计数器在适当的方向以及先前值、当前值和下一个值递增。它不修改原始数组。

我还对你的代码片段进行了计时,虽然它不快,但是比你的代码片段要快——慢21% 的 http://jsperf.com/js-rotate-array/7

function directionalRotate(direction, counter, arr) {
counter = direction ? (counter < arr.length - 1 ? counter + 1 : 0) : (counter > 0 ? counter - 1 : arr.length - 1)
var currentItem = arr[counter]
var priorItem = arr[counter - 1] ? arr[counter - 1] : arr[arr.length - 1]
var nextItem = arr[counter + 1] ? arr[counter + 1] : arr[0]
return {
"counter": counter,
"current": currentItem,
"prior": priorItem,
"next": nextItem
}
}
var direction = true // forward
var counter = 0
var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];


directionalRotate(direction, counter, arr)

http://jsperf.com/js-rotate-array/8

function reverse(a, from, to) {
--from;
while (++from < --to) {
var tmp = a[from];
a[from] = a[to];
a[to] = tmp;
}
}


function rotate(a, from, to, k) {
var n = to - from;
k = (k % n + n) % n;
if (k > 0) {
reverse(a, from, from + k);
reverse(a, from + k, to);
reverse(a, from, to);
}
}

你可以使用 push()pop()shift()unshift()的方法:

function arrayRotate(arr, reverse) {
if (reverse) arr.unshift(arr.pop());
else arr.push(arr.shift());
return arr;
}

用途:

arrayRotate([1, 2, 3, 4, 5]);       // [2, 3, 4, 5, 1];
arrayRotate([1, 2, 3, 4, 5], true); // [5, 1, 2, 3, 4];

如果你需要 count参数,请看我的另一个答案:
Https://stackoverflow.com/a/33451102

这些答案中有许多似乎过于复杂和难以阅读。 我没看到有人用拼接连接..。

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

console.log outputs (*generated in May):

["May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr"]

至于紧凑性,我可以提供一些通用的一行程序函数(不包括 console.log | return 部分)。只需在参数中向它提供数组和目标值。

我将这些函数合并为一个四人纸牌游戏程序,其中的数组为[‘ 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;
}

组合函数。

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

调整数组 =

W,N,E,S

This function works in both way and works with any number (even with number greater than array length):

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

用途:

for(let i = -6 ; i <= 6 ; i++) {
console.log(arrayRotate(["🧡","💚","💙","💜","🖤"], i), i);
}

结果:

[ "🖤", "🧡", "💚", "💙", "💜" ]    -6
[ "🧡", "💚", "💙", "💜", "🖤" ]    -5
[ "💚", "💙", "💜", "🖤", "🧡" ]    -4
[ "💙", "💜", "🖤", "🧡", "💚" ]    -3
[ "💜", "🖤", "🧡", "💚", "💙" ]    -2
[ "🖤", "🧡", "💚", "💙", "💜" ]    -1
[ "🧡", "💚", "💙", "💜", "🖤" ]    0
[ "💚", "💙", "💜", "🖤", "🧡" ]    1
[ "💙", "💜", "🖤", "🧡", "💚" ]    2
[ "💜", "🖤", "🧡", "💚", "💙" ]    3
[ "🖤", "🧡", "💚", "💙", "💜" ]    4
[ "🧡", "💚", "💙", "💜", "🖤" ]    5
[ "💚", "💙", "💜", "🖤", "🧡" ]    6

接受的答案有一个缺陷,即不能处理大于调用堆栈大小的数组,这取决于会话,但应该是大约100 ~ 300K 项。例如,在当前的 Chrome 会话,我尝试它是250891。在许多情况下,您甚至不知道数组可能会动态增长到什么大小。所以这是个严重的问题。

为了克服这个限制,我猜想一个有趣的方法是利用 Array.prototype.map()并通过循环方式重新排列索引来映射元素。此方法接受一个整数参数。如果这个参数是正的,它会在增加的指数上旋转,如果是负的,它会在减少的指数方向上旋转。这只有 O (n)时间复杂度,并且将返回一个新的数组,而不会在处理数百万个项目时对所调用的数组进行变异,而且没有任何问题。让我们看看它是如何工作的;

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

其实在我被批评之后的两件事情是这样的:

  1. 没有必要为积极或消极的输入条件,因为它揭示了一个违反 DRY。你可以用一个映射做到这一点,因为每个负 n 都有一个正的等价物(完全正确。.)
  2. Array 函数应该要么更改当前数组,要么创建一个新数组,这取决于是否需要移位(完全正确)。.)

我已经决定修改代码如下;

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

当然,像 Array.prototype.map()这样的 JS 函数比用普通 JS 编码的等价函数要慢。为了获得超过100% 的性能提升,以下可能是我的选择 Array.prototype.rotate(),如果我曾经需要在生产代码中旋转一个数组,就像我在 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;
};

2022及就位

你也可以像这样单次旋转

function rotateArrayInPlaceByOne(a){
[a[a.length-1],a] = [a[0],a.copyWithin(0,1,a.length)];
return a;
}

在 V8中,无论是使用数组解构还是临时交换元素,这一行都比上面的答案稍慢。http://jsben.ch/6fFyr

这里有一个非常简单的方法来移动数组中的项:

function rotate(array, stepsToShift) {


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


return array;
}

这个函数比小数组的可接受答案稍微快一点,但是对于大数组要快得多。这个函数还允许任意数量的旋转大于数组的长度,这是原始函数的一个限制。

最后,接受的答案旋转相反的方向,如所述。

const rotateForEach = (a, n) => {
const l = a.length;
a.slice(0, -n % l).forEach(item => a.push( item ));
return a.splice(n % l > 0 ? (-n % l) : l + (-n % l));
}

功能等价物(似乎也有一些性能优势) :

const rotateReduce = (arr, n) => {
const l = arr.length;
return arr.slice(0, -n % l).reduce((a,b) => {
a.push( b );
return a;
}, arr).splice(n % l> 0 ? l + (-n % l) : -n % l);
};

你可以看看 表现不佳。

我要迟到了,但我还有一块砖头要补充这些好的答案。 我被要求编写这样一个函数,我首先这样做了:

Array.prototype.rotate = function(n)
{
for (var i = 0; i < n; i++)
{
this.push(this.shift());
}
return this;
}

但在 n规模较大时,它的效率似乎低于后者:

Array.prototype.rotate = function(n)
{
var l = this.length;// Caching array length before map loop.


return this.map(function(num, index) {
return this[(index + n) % l]
});
}

编辑: 结果发现迭代太多了,没有循环,没有分支。

Still works with negative n for right rotation and positive n for left rotation for any size n, 没有变异

function rotate(A,n,l=A.length) {
const offset = (((n % l) + l) %l)
return A.slice(offset).concat(A.slice(0,offset))
}

这是“咯咯笑”的高尔夫代码版本

const r = (A,n,l=A.length,i=((n%l)+l)%l)=>A.slice(i).concat(A.slice(0,i))

Branchless, mutationless implementation.

So hey, turns out I had a branch where I didn't need it. Here is a working solution. 负 num = 由 | num | 向右旋转 正数 num = 左旋转

function r(A,n,l=A.length) {
return A.map((x,i,a) => A[(((n+i)%l) + l) % l])
}

方程 ((n%l) + l) % l精确地映射任意大的 n 值的正数和负数

原创的

旋转左右。旋转左与正的 n,旋转右与负的 n

适用于 n的超大输入。

没有变异模式,答案中有太多变异。

此外,操作比大多数答案少。没有弹出,没有推,没有拼接,没有转移。

const rotate = (A, num ) => {
return A.map((x,i,a) => {
const n = num + i
return n < 0
? A[(((n % A.length) + A.length) % A.length)]
: n < A.length
? A[n]
: A[n % A.length]
})
}

或者

 const rotate = (A, num) => A.map((x,i,a, n = num + i) =>
n < 0
? A[(((n % A.length) + A.length) % A.length)]
: n < A.length
? A[n]
: A[n % A.length])


//test
rotate([...Array(5000).keys()],4101)   //left rotation
rotate([...Array(5000).keys()],-4101000)  //right rotation, num is negative


// will print the first index of the array having been rotated by -i
// demonstrating that the rotation works as intended
[...Array(5000).keys()].forEach((x,i,a) => {
console.log(rotate(a,-i)[0])
})
// prints even numbers twice by rotating the array by i * 2 and getting the first value
//demonstrates the propper mapping of positive number rotation when out of range
[...Array(5000).keys()].forEach((x,i,a) => {
console.log(rotate(a,i*2)[0])
})

说明:

将 A 的每个索引映射到索引偏移处的值

offset = num

if the offset < 0 then offset + index + positive length of A will point to the inverse offset.

如果 offset > 0 and offset < length of A,那么只需将当前索引映射到 A 的偏移量索引。

否则,将偏移量和长度模化,以映射数组边界中的偏移量。

offset = 4offset = -4为例。

When offset = -4, and A = [1,2,3,4,5], for each index, offset + index will make the magnitude (or Math.abs(offset)) smaller.

Let's explain the calculation for the index of negative n first. A[(((n % A.length) + A.length) % A.length)+0] and been intimidated. 不用道歉。 It took me 3 minutes in a Repl to work it out.

  1. 我们知道 n是阴性的,因为病例是 n < 0。如果数字大于 Array 的范围,n % A.length将把它映射到该范围。
  2. 将该数字添加到 A.length以正确偏移 n 金额。
  3. 我们知道 n是阴性的,因为病例是 n < 0n + A.length将该数字加到 A.length以抵消 n 的正确数量。
  4. 接下来,使用模把它映射到 A 的长度范围。为了将计算结果映射到一个可转位的范围,第二个模块是必需的

    enter image description here

  5. 第一个索引: -4 + 0 = -4。长度 = 5。长度 -4 = 1。A2是2。地图索引0到2。[2,... ]

  6. 下一个索引,-4 + 1 = -3。5 + -3 = 2.A2是3。地图索引1至3。[2,3... ]
  7. 等等。

同样的过程也适用于 offset = 4。 当 offset = -4A = [1,2,3,4,5]对应每个指数时,offset + index的震级会变大。

  1. 将 A [0]映射到 A [4]处的值
  2. 4 + 1 = 5, 5 is out of bounds when indexing, so map A2 to the 值为 5 / 5的其余部分,即0 A [0]
  3. 重复。

Using ES6's spread for an immutable example ...

[...array.slice(1, array.length), array[0]]

还有

[array[array.items.length -1], ...array.slice(0, array.length -1)]

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

I am not sure if this is the most efficient way but I like the way it reads, it's fast enough for most large tasks as I have tested it on production...

function shiftRight(array) {
return array.map((_element, index) => {
if (index === 0) {
return array[array.length - 1]
} else return array[index - 1]
})
}


function test() {
var input = [{
name: ''
}, 10, 'left-side'];
var expected = ['left-side', {
name: ''
}, 10]
var actual = shiftRight(input)


console.log(expected)
console.log(actual)


}


test()

Follow a simpler approach of running a loop to n numbers and shifting places upto that element.


function arrayRotateOne(arr, n) {
for (let i = 0; i < n; i++) {
arr.unshift(arr.pop());
}
return arr;
}
console.log( arrayRotateOne([1,2,3,4,5,6],2));






function arrayRotateOne(arr,n) {
for(let i=0; i<n;i++){
arr.push(arr.shift());
console.log('execute',arr)
}
return arr;
}

Log (arrayRotateOne ([1,2,3,4,5,6] ,2) ;

非变异解决方案

var arr = ['a','b','c','d']
arr.slice(1,arr.length).concat(arr.slice(0,1)

with mutation

var arr = ['a','b','c','d']
arr = arr.concat(arr.splice(0,1))

我正在分享我的解决方案,我正在使用旋转木马。 It might break when array size is smaller than displayCount, but you could add extra condition to stop rotating when it's small, or concatenating the main array *displayCount times too.

function rotate(arr, moveCount, displayCount) {
const size = arr.length;


// making sure startIndex is between `-size` and `size`
let startIndex = moveCount % size;
if (startIndex < 0) startIndex += size;


return [...arr, ...arr].slice(startIndex, startIndex + displayCount);
}


// move 3 to the right and display 4 items
// rotate([1,2,3,4,5], 3, 4) -> [4,5,1,2]


// move 3 to the left and display 4 items
// rotate([1,2,3,4,5], -3, 4) -> [3,4,5,1]


// move 11 to the right and display 4
// rotate([1,2,3,4,5], 3, 4) -> [2,3,4,5]

简单易行的解决方案:

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]

原生的,快速的,小的,语义的,工作在旧的引擎和“咖喱”。

function rotateArray(offset, array) {
offset = -(offset % array.length) | 0 // ensure int
return array.slice(offset).concat(
array.slice(0, offset)
)
}

** Using Latest version of JS we can build it every easily **

 Array.prototype.rotateLeft = function (n) {
this.unshift(...this.splice(-(n), n));
return this
}

这里移动: 旋转次数,一个数组 你可以传递随机数

let a = [1, 2, 3, 4, 5, 6, 7];
let moves = 4;
let output = a.rotateLeft(moves);
console.log("Result:", output)

JS 中的 Array有以下内置的方法,可以很容易地用来旋转一个数组,显然这些方法本质上是 永恒不变

  • 将项插入到数组的末尾。
  • 从数组末尾移除该项。
  • unshift: Inserts the item to the beginning of the array.
  • shift: Removes the item from the beginning of the array.

下面的解(ES6)有两个参数,数组需要旋转,n,数组需要旋转的次数。

const rotateArray = (arr, n) => {
while(arr.length && n--) {
arr.unshift(arr.pop());
}
return arr;
}


rotateArray(['stack', 'overflow', 'is', 'Awesome'], 2)
// ["is", "Awesome", "stack", "overflow"]

它可以被添加到 Array.model 中,并且可以在整个应用程序中使用

Array.prototype.rotate = function(n) {
while(this.length && n--) {
this.unshift(this.pop());
}
return this;
}
[1,2,3,4].rotate(3); //[2, 3, 4, 1]

不知道效率如何,但我会用这种不变异的方式来做:

	Array.prototype.rotate = function( n ) {
  

return this.map( (item, index)=> this[ (this.length + index + n)%this.length ] )
}

使用 for 循环

  1. 将数组的第一个元素存储为临时变量。
  2. 然后从左到右交换。
  3. 然后将临时变量赋给数组的最后一个元素。
  4. 对于旋转次数重复这些步骤。

function rotateLeft(arr, rotations) {
let len = arr.length;
for(let i=0; i<rotations; i++){
let temp = arr[0];
for(let i=0; i< len; i++){
arr[i]=arr[i+1];
}
arr[len-1]=temp;
}
return arr;
}


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


let rotations = 3;
let output = rotateLeft(arr, rotations);
console.log("Result Array => ", output);

function rotate(arr, k) {
for (var i = 0; i < k+1; i++) {
arr.push(arr.shift());
}
return arr;
}
//k work as an index array
console.log(rotate([1, 2, 7, 4, 5, 6, 7], 3)); //[5,6,7,1,2,7,4]
console.log(rotate([-1, -100, 3, 99], 2));     //[99,-1,-100,3]
// Example of array to rotate
let arr = ['E', 'l', 'e', 'p', 'h', 'a', 'n', 't'];


// Getting array length
let length = arr.length;


// rotation < 0 (move left), rotation > 0 (move right)
let rotation = 5;


// Slicing array in two parts
let first  = arr.slice(   (length - rotation) % length, length); //['p', 'h', 'a' ,'n', 't']
let second = arr.slice(0, (length - rotation) % length); //['E', 'l', 'e']


// Rotated element
let rotated = [...first, ...second]; // ['p', 'h', 'a' ,'n', 't', 'E', 'l', 'e']


在一行代码中:

let rotated = [...arr.slice((length - rotation) % length, length), ...arr.slice(0, (length - rotation) % length)];

使用 es6语法

function rotLeft(a, d) {
const removed = a.splice(0,d);
return [...a, ...removed];
}

使用以下-

arr=[1,2,3,4,5]
let arrs=[]
arrs=arr.slice(d%arr.length).concat(arr.slice(0,d%arr.length))

在哪里,d是不是旋转
最佳解决方案,不需要应用蛮力推挤技术 O (1) 时间复杂度

function solution (months, k) {
var u = [1];
for (let i = 0; i < k; i++) {
months.splice(0, 0, months[months.length - 1]);
months.splice(months.length-1, 1);
}
return months;
}

我这样做没有任何帮助程序库

function shiftArrayValuesRight(A, K) {
// where A is the array, K is the number of times to shift
let b = []
if(A.length > 0) {
for(let i = 0; i < K; i++){
b[0] = A[A.length - 1]
for(let j = 1; j < A.length; j++) {
b[j] = A[j-1]
}
A = b
b = []
}
return A
} else{
return A
}
}

2021年2月更新

执行数组元素的 向右转向左旋转的一行函数。

左转

const arrRotateLeft = (a,n) =>{while (n>0) {a.push(a.shift());n--;}return a;};

右转

const arrRotateRight= (a,n) =>{while (n>0) {a.unshift(a.pop());n--;}return a;};

const arrRotateLeft = (a,n)=>{while (n>0) {a.push(a.shift());n--;}return a;};


const arrRotateRight= (a,n)=>{while (n>0) {a.unshift(a.pop());n--;}return a;};




//=========== Test rotate Left =================
console.log(arrRotateLeft([1,2,3,4,5,6],0));       // [1,2,3,4,5,6]   <== rotate in this direction
console.log(arrRotateLeft([1,2,3,4,5,6],1));       // [2,3,4,5,6,1]
console.log(arrRotateLeft([1,2,3,4,5,6],2));       // [3,4,5,6,1,2]
console.log(arrRotateLeft([1,2,3,4,5,6],3));       // [4,5,6,1,2,3]
console.log(arrRotateLeft([1,2,3,4,5,6,7,8],5));   // [6,7,8,1,2,3,4,5]




//=========== Test rotate Right =================
console.log(arrRotateRight([1,2,3,4,5,6],0));      // [1,2,3,4,5,6]   ==> rotate in this direction
console.log(arrRotateRight([1,2,3,4,5,6],1));      // [6,1,2,3,4,5]
console.log(arrRotateRight([1,2,3,4,5,6],2));      // [5,6,1,2,3,4]
console.log(arrRotateRight([1,2,3,4,5,6],3));      // [4,5,6,1,2,3]
console.log(arrRotateRight([1,2,3,4,5,6,7,8],5));  // [4,5,6,7,8,1,2,3]

let array = [3, 9, 2, 4, 5, 7, 8];


const shiftLeft = (arr = [], n) => {
for (let index = 0; index < n; index++) {
arr.push(arr.shift())
}
return arr
}

Shift 左(数组,2)

不要使用 concatsplice或其他任何东西。使用 .map或一个 while循环为一个简单,有效的方式旋转左或右。其思想是迭代原始数组的长度。在每次迭代时,更新要添加到新旋转的数组中的旋转中下一个值的索引。这个解决方案是 O (n)时间复杂性——在两个示例中只有一个循环。

地图:

function Rotate(arr, n) {
if (n === 0) {
return arr;
}


var left = n < 0;
n = Math.abs(left ? n : arr.length - n);


return arr.map(() => {
n = n < arr.length ? n : 0;


return arr[n++];
});
}


var array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var places = 4;


console.log(Rotate(array, places));//[12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
console.log(Rotate(array, -places));//[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3]

同时:

function Rotate(arr, n) {
if (n === 0) {
return arr;
}


var rotatedArray = [];
var left = n < 0;
n = Math.abs(left ? n : arr.length - n);


while (rotatedArray.length < arr.length) {
n = n < arr.length ? n : 0;
rotatedArray.push(arr[n++]);
}


return rotatedArray;
}

spliceconcat方法是 O (n)操作; 前者删除并返回一个“拼接”值数组,后者返回一个包含合并数组值的新数组。因此,如果同时使用这两个数组,就要做太多的工作: O (n) * 2和两个新复制的数组。坦率地说,通过一个简单的 while循环更容易理解其中的逻辑。

for rotating the array by 'd' places towards the left we can use unshift() and pop().

   var arr=[1,2,3,4,5],d=4;
for(var i=d;i<arr.length;i++)
arr.unshift(arr.pop());
console.log(arr);

对于黑客级别,问题解决 DS 左右旋转问题解决方案(javascript,java)检查我下面的文章

Https://webdev99.com/left-rotationproblem-solving-data-structures/

What about a more functional approach?

const rotate = _.curry((n,v) => {
const M = v.length;
const m = ((n % M) + M) % M;
return _.flatten([_.drop(m, v), _.take(m, v)]);
});

如果不需要负的 n,可以简化为

const rotate = _.curry((n,v) => {
const N = v.length;
return _.flatten([_.drop(n % N, v), _.take(n % N, v)]);
});

如果 n保证不大于 v.length,那么我们可以进一步简化:

const rotate = _.curry((n,v) => _.flatten([_.drop(n, v), _.take(n, v)]));

这里是一行程序的解决方案,利用扩展和切片。

旋转有两种方式: 如果你想向右移动,你需要提供一个负值; 但是如果你向左移动,你就提供一个正值。

rotateLeft(arr, 1) === rotateRight(arr, -1)

如下图所示,带正值的旋转自然会向左移动。

console.json = (json) => console.log(JSON.stringify(json));


const
rotateLeft  = (arr, n) =>
n ? [...arr.slice( n, arr.length), ...arr.slice(0,  n)] : arr,
rotateRight = (arr, n) =>
n ? [...arr.slice(-n, arr.length), ...arr.slice(0, -n)] : arr;


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


console.log('Rotate left:');
console.json(rotateLeft(arr,  1));  // [2, 3, 4, 5, 1]
console.json(rotateLeft(arr,  2));  // [3, 4, 5, 1, 2]
console.json(rotateLeft(arr, -2));  // [4, 5, 1, 2, 3]
console.json(rotateLeft(arr, -1));  // [5, 1, 2, 3, 4]
console.json(rotateLeft(arr,  0));  // [1, 2, 3, 4, 5] (no-op)


console.log('Rotate right:');
console.json(rotateRight(arr,  1)); // [5, 1, 2, 3, 4]
console.json(rotateRight(arr,  2)); // [4, 5, 1, 2, 3]
console.json(rotateRight(arr, -2)); // [3, 4, 5, 1, 2]
console.json(rotateRight(arr, -1)); // [2, 3, 4, 5, 1]
console.json(rotateRight(arr,  0)); // [1, 2, 3, 4, 5] (no-op)
.as-console-wrapper { top: 0; max-height: 100% !important; }

from 2022

我认为这种方法是最简单的

// 0. fix the index
// 1. remove the rotation part
// 2. add a reversed version of the rotation part to what left
// done


function rotateArray(array, k) {
let rev = k > 0;
array = [...array];
      

k = ( k + array.length) % array.length;
const splice = array.splice(0, k); //... for make a clone;
return array.concat(rev ? splice.reverse() : splice);
}


console.log(rotateArray([1,2,3,4,5,6,7], 3)) // expect [4,5,6,7,1,2,3]
console.log(rotateArray([1,2,3,4,5,6,7], -3))// expect [5,6,7,1,2,3,4]

我喜欢 "Yukulélé"的答案; 但是我喜欢调整这个想法,并像这样实现它:

我不认为我目前的答案是最有效的版本,因为它使用了类似递归的思想; 购买,顺便说一下,我喜欢分享它:)

定义原型

Array.prototype.rotateLeft = function (n = 1) {
n > 1 ? this.rotateLeft(n - 1) : this.push(this.shift())
}


Array.prototype.rotateRight = function (n = 1) {
n > 1 ? this.rotateRight(n - 1) : this.unshift(this.pop())
}

简单用法

arr = [3, 4, 5, 6, 7, 8]
console.log(arr)
// [ 3, 4, 5, 6, 7, 8 ]


arr.rotateLeft()
console.log(arr)
// [ 4, 5, 6, 7, 8, 3 ]


arr.rotateRight()
console.log(arr)
//[ 3, 4, 5, 6, 7, 8 ]


arr.rotateRight()
console.log(arr)
//[ 8, 3, 4, 5, 6, 7 ]

使用不同数量的参数 n

arr = [3, 4, 5, 6, 7, 8]
console.log(arr)
// [ 3, 4, 5, 6, 7, 8 ]


arr.rotateRight(3)
console.log(arr)
//[ 6, 7, 8, 3, 4, 5 ]