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

Posted

技术标签:

【中文标题】将第一个元素移动到数组末尾的最快方法【英文标题】:Fastest way to move first element to the end of an Array 【发布时间】:2013-12-21 13:21:09 【问题描述】:

我想知道在 javascript 中将元素从 Array 的开头移动到结尾的最快方法是什么。例如,如果我们有

[8,1,2,3,4,5,6,7]

我们想要:[1,2,3,4,5,6,7,8]

我想将第一个元素移到末尾。我正在考虑将元素 0 与元素 1 切换,然后将元素 1 与元素 2 切换,依此类推,直到 8 位于 and (基本上是冒泡排序的工作原理)。我想知道是否有更快的方法将第一个元素带到最后。

我将使用小型数组(大约 10 个元素),并且我想避免使用 shift(),因为它非常慢。

这就是我现在在 chrome 上所拥有的,它比普通 shift+push 快 45%:http://jsperf.com/shift-myfunc

数组中将包含用于游戏的对象。

【问题讨论】:

很遗憾 OP 如何寻找 fastest 方式而不仅仅是 a 并且人们给出一般性答案而没有解释为什么他们更快/比替代品慢。我猜是FGITW。 OP,您的具体用例是什么?你的目标是什么浏览器?数组有多大(它们总是 ~8 个元素吗?它们是 10K 元素吗?),如果你想要真正的基准测试,你需要更加具体。 感谢编辑澄清 - 下一轮:它们是像 [1,2,,,5,8] 那样稀疏的数组还是它们总是满(就像你的例子),它们总是只包含整数吗?您的目标浏览器/引擎是什么?您每秒最多需要进行多少次此类转换的迭代? @BenjaminGruenbaum 如果 OP 事先说明他们尝试了什么并且可能没有一般性的答案,那将会有所帮助。有问题的努力=回答的努力。使用 JSPerf 进行简单的测试会很好。 :) @epascarello True - fastest 做某事的方式在这里非常依赖于目标 JS 引擎、数组大小、它包含的内容等等 - 我'我还在等待被说服 OP 真的需要它那么快并且需要付出什么代价(例如,如果他经常旋转,那么将数组的副本连接到自身并对其进行切片可能会很好,使用类型化数组或使用其他有用的技巧)。我知道 you 和 j08691 绝对是这里的好人,因为他们知道你的许多其他答案,但鉴于模棱两可,回答一个似乎毫无意义。 【参考方案1】:

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

【讨论】:

对于任何未来的绕过者,它的工作原理是使用 Shift 功能。它删除数组中的第一项,然后将其返回。换句话说,这段代码删除了数组中的第一项,然后再次添加它——使其进入数组的底部。 漂亮优雅。 做得很好...我一直在寻找相反的结果,但想出了这个答案,所以经过一些快速研究后,这里是执行上述操作的相反方式... ary.unshift(ary.pop ());【参考方案2】:

使用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


真正最快的是什么?

什么是最快的实际上取决于你对数组做什么。如果您只是使用第一个索引,那么让您的代码读取索引而不移动值将是最快的。如果您正在使用所有索引,则不仅仅是循环遍历,当您到达终点时,从零开始。基本计数器。

【讨论】:

我想避免使用 shift 因为它很慢。 不如在你的问题中这么说! @user2815780 - 也许您应该在问题中发布您已经尝试过的内容,包括统计数据以显示什么是快什么是慢? 我用方法和 JSPerf 更新了我的答案。我确信我的循环答案可以改进,我只是把它放在一起作为我实际工作的休息时间。 请注意 splice() 返回一个数组,因此名为“splice-push”(我个人偏好)的测试并非 100% 正确。应该是:var b = arr.splice(0, 1); arr.push(b[0]);【参考方案3】:

这是一个甜蜜的 ES6 版本

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

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

【讨论】:

真的很甜蜜【参考方案4】:

使用拼接获取第一个元素

var first = array.splice(0,1);

如果是最后一个,则推入。

既然splice方法的返回值是一个数组,那不得不说

array.push(first[0]);

这里的工作示例:JSFIDDLE

【讨论】:

【参考方案5】:

以防万一你想把任何元素放在最后:

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

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

【讨论】:

ary.push(ary.slice(position, 1)); 是错误的,如果 position 为 0,将导致 [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。无论哪种方式,切片/拼接都返回一个数组,因此您必须推送 arr 的第一项,而不是 arr 本身。我修复了代码:ary.push(ary.splice(0, 1)[0]);【参考方案6】:
var a = [1,2,3,4,5,6,7,8];
var b= a[7];
var c = a.slice(1, 8);
c.push(b);

编辑: 像 epascarello 在his answer 中所做的那样,换班可能会更好。

【讨论】:

【参考方案7】:

使用 ES20...

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

【讨论】:

【参考方案8】:

另一种味道

var arr = [0, 1, 2];
arr = arr.concat(arr.shift())

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

【讨论】:

【参考方案9】:

更新数组,将元素从一个极端移动到另一个极端:

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' ]

【讨论】:

以上是关于将第一个元素移动到数组末尾的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

如何将第一个数字移动到c ++中数字的末尾?

通过在前一个数组的末尾存储下一个元素来扩展数组

为啥bash只将第一个元素附加到数组

C++ - 将项目添加到排序数组的最快方法

在python中将所有零移动到数组的末尾

js哪些方法改变原数组哪些不改变原数组