将数组的第一个元素移动到末尾的最快方法

71
我想知道在 JavaScript 中最快的方式是什么,可以将一个元素从 Array 的开头移到末尾。例如,如果我们有 [8,1,2,3,4,5,6,7],并且我们想要 [1,2,3,4,5,6,7,8]。我想把第一个元素移到末尾。我考虑过交换元素 0 和元素 1,然后交换元素 1 和元素 2,以此类推,直到 8 在末尾(基本上就像冒泡排序一样)。我想知道是否有更快的方法将第一个元素移到末尾。
我将使用小数组(约10个元素),而且我想避免使用shift(),因为它非常慢。
这是我现在拥有的,在 Chrome 上比普通的 shift+push 快了45%:http://jsperf.com/shift-myfunc 数组中将有游戏对象。

4
很遗憾,OP正在寻找“最快”的方法而不是只有“一个”,人们提供了一般性的答案,没有解释为什么它们比其他选择更快/慢。我猜这就是首先到达者的优势。OP,你具体的使用场景是什么?你要针对哪些浏览器进行优化?数组有多大(它们总是约8个元素吗?还是10K个元素?)如果你想进行真正的基准测试,你需要更加具体。 - Benjamin Gruenbaum
1
感谢您编辑以澄清 - 下一轮:它们是否像[1,2,,,5,8]这样稀疏,还是始终为满(如您的示例),它们是否始终仅包含整数?您要针对哪些浏览器/引擎进行定位,并且每秒最多需要执行多少次这些排序移位操作? - Benjamin Gruenbaum
2
@BenjaminGruenbaum 如果楼主一开始就说明了他们尝试过的内容,也许就不会有那么多泛泛而谈的回答了。问题的付出等于回答的付出。用JSPerf进行简单测试会很好的。 :) - epascarello
1
@epascarello 确实 - 做某事的最快方式非常依赖于目标JS引擎、数组大小、它所包含的内容等因素 - 我还在等待被说服OP确实需要以这种方式快速完成,并且以何种代价(如果例如他经常旋转,可能很好将数组的副本连接到自身并对其进行切片、使用类型数组或使用其他有用的技巧)。我知道 和 j08691 从你们的其他答案中了解到你们绝对是好人,但回答一个似乎有点无意义,因为存在歧义。 - Benjamin Gruenbaum
9个回答

131

使用shift()和push()函数:

var ary = [8,1,2,3,4,5,6,7];
ary.push(ary.shift());  // results in [1, 2, 3, 4, 5, 6, 7, 8] 

示例:

var ary = [8,1,2,3,4,5,6,7];

console.log("Before: " + ary);

ary.push(ary.shift());  // results in [1, 2, 3, 4, 5, 6, 7, 8] 

console.log("After: " + ary);


13
对于未来的路过者,这个代码使用了Shift函数。它会移除数组中的第一个项目,并返回该项目。换句话说,这段代码会移除数组中的第一个项目,然后再将其添加回去,从而使其移到数组底部。 - Alex
5
优美而优雅。 - sfors says reinstate Monica
5
做得非常好...我本来在寻找相反的方法,但找到了这个答案,于是经过一些快速的研究,以下是相反的操作方式...ary.unshift(ary.pop()); - Digggid

26

使用shiftpush

var a = ["a","b","c"];
var b = a.shift();
a.push(b);
或者
var b = a.shift();
a[a.length] = b;

根据更新后的问题进行编辑

什么会是最快的?真正取决于数组的内容和浏览器/版本!

现在有哪些方法可以删除第一个索引?

  • shift()
  • splice()
  • slice()

现在有哪些方法可以添加到最后一个索引?

  • push()
  • array[array.length]
  • concat() - 我甚至不想尝试

其他方法

  • for循环 - 创建新数组[对大型数组会产生负面影响]

JSPerf:

http://jsperf.com/test-swapping-of-first-to-last


什么才是真正的最快?

什么才是最快的,实际上取决于你对数组的具体操作。如果你只使用第一个索引,那么最快的方法就是直接读取该索引而不是移动值。如果你需要使用所有索引,那么最好的方法就是通过循环遍历整个数组,在到达末尾后回到索引0。基本上是计数器。


1
我想避免使用移位操作,因为它相当慢。 - Bosiwow
7
那么在你的问题中说出来吧! - epascarello
2
@user2815780 - 也许你应该在问题中发布你已经尝试过的内容,包括统计数据以显示什么是快的和慢的? - j08691
1
我更新了我的答案,并提供了实现方法和JSPerf。我相信我的循环答案可以改进,只是为了从我的真正工作中休息而随意组合的。 - epascarello
1
请注意,splice()返回一个数组,因此名为“splice-push”的测试(我的个人偏好)并不完全正确。应该是:var b = arr.splice(0, 1); arr.push(b[0]); - BoDeX

18

这里是一个甜美的 ES6 版本

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

const [first, ...rest] = arr;
arr = [...rest,first]

2
那真的很棒。 - mtyson

9
使用splice方法获取第一个元素。
var first = array.splice(0,1);

如果是最后一个,则进行推送操作。

由于splice方法的返回值是一个数组,因此你需要写成:

array.push(first[0]);

这里有一个工作示例:JSFIDDLE


7

如果您想将任何元素放到末尾:

var ary = [8,1,2,3,4,5,6,7];
ary.push(ary.splice(position, 1)[0]);

对于position,只需在forEach中包装即可。


4
еҰӮжһң position дёә 0пјҢеҲҷ ary.push(ary.slice(position, 1)) жҳҜй”ҷиҜҜзҡ„пјҢз»“жһңдјҡеҸҳжҲҗ [8,1,2,3,4,5,6,7,Array[1]пјӣеҰӮжһң position дёә 1пјҢеҲҷз»“жһңдјҡеҸҳжҲҗ [8,1,2,3,4,5,6,7,Array[0]гҖӮжҲ‘зҢңдҪ жғідҪҝз”Ё splice иҖҢдёҚжҳҜ sliceпјҢеӣ дёә slice дёҚдјҡеҲ йҷӨйЎ№зӣ®пјҢ并且е®ғдҪҝз”Ёзҡ„еҸӮж•°еҲ—иЎЁжҳҜ start, end иҖҢдёҚжҳҜ start, deleteCountгҖӮж— и®әеҰӮдҪ•пјҢslice/splice йғҪиҝ”еӣһдёҖдёӘж•°з»„пјҢжүҖд»ҘдҪ еҝ…йЎ»жҺЁйҖҒж•°з»„зҡ„第дёҖдёӘйЎ№пјҢиҖҢдёҚжҳҜж•ҙдёӘж•°з»„жң¬иә«гҖӮжҲ‘е·Із»Ҹдҝ®еӨҚдәҶд»Јз Ғпјҡary.push(ary.splice(0, 1)[0])гҖӮ - Drkawashima

3
var a = [1,2,3,4,5,6,7,8];
var b= a[7];
var c = a.slice(1, 8);
c.push(b);

编辑:最好只是像epascarello在他的答案中所做的那样进行移位。


3

With ES20...

const newArr = [
   ...arr.slice(1),
   arr[0]
];

2
一个更多的口味。
var arr = [0, 1, 2];
arr = arr.concat(arr.shift())

concat 可以在末尾或开头添加不仅仅是一个元素,还可以是另一个数组


0

将数组中的元素从一端移动到另一端进行更新:

const array = ['First', 'Second', 'Third', 'Fourth'];

const next = [...array]
next.push(next.shift())
console.log(next); // [ 'Second', 'Third', 'Fourth', 'First' ]

const prev = [...array]
prev.unshift(prev.pop())
console.log(prev); // [ 'Fourth', 'First', 'Second', 'Third' ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接