将第一个元素移动到数组末尾的最快方法
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】:使用shift
和push
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' ]
【讨论】:
以上是关于将第一个元素移动到数组末尾的最快方法的主要内容,如果未能解决你的问题,请参考以下文章