在 Javascript 中反转数组的最有效方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5276953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the most efficient way to reverse an array in Javascript?
提问by luisgo
I was asked recently what was the most efficient way to reverse an array in Javascript. At the moment, I suggested using a for loop and fiddling with the array but then realized there is a native Array.reverse()
method.
最近有人问我在 Javascript 中反转数组的最有效方法是什么。目前,我建议使用 for 循环并摆弄数组,但后来意识到有一个本机Array.reverse()
方法。
For curiosity's sake, can anyone help me explore this by showing examples or pointing in the right direction so I can read into this? Any suggestions regarding how to measure performance would be awesome too.
出于好奇,任何人都可以通过展示示例或指向正确的方向来帮助我探索这一点,以便我可以阅读此内容吗?任何关于如何衡量性能的建议也会很棒。
回答by XP1
Based on this setup:
基于此设置:
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var length = array.length;
Array.reverse();
is the first or second slowest!
Array.reverse();
是第一个还是第二个最慢!
The benchmarks are here:
基准点在这里:
https://jsperf.com/js-array-reverse-vs-while-loop/9
https://jsperf.com/js-array-reverse-vs-while-loop/9
Across browsers, swap loops are faster. There are two common types of swap algorithms (see Wikipedia), each with two variations.
跨浏览器,交换循环更快。有两种常见类型的交换算法(请参阅维基百科),每种算法都有两种变体。
The two types of swap algorithms are temporary swap and XOR swap.
两种交换算法是临时交换和异或交换。
The two variations handle index calculations differently. The first variation compares the current left index and the right index and then decrements the right index of the array. The second variation compares the current left index and the length divided by half and then recalculates the right index for each iteration.
这两种变体以不同的方式处理索引计算。第一个变体比较当前的左索引和右索引,然后递减数组的右索引。第二个变体比较当前左索引和除以一半的长度,然后为每次迭代重新计算右索引。
You may or may not see huge differences between the two variations. For example, in Chrome 18, the first variations of the temporary swap and XOR swap are over 60% slower than the second variations, but in Opera 12, both variations of the temporary swap and XOR swap have similar performance.
您可能会也可能不会看到这两种变体之间的巨大差异。例如,在 Chrome 18 中,临时交换和 XOR 交换的第一个变体比第二个变体慢 60% 以上,但在 Opera 12 中,临时交换和 XOR 交换的两个变体具有相似的性能。
Temporary swap:
临时交换:
First variation:
第一个变化:
function temporarySwap(array)
{
var left = null;
var right = null;
var length = array.length;
for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
{
var temporary = array[left];
array[left] = array[right];
array[right] = temporary;
}
return array;
}
Second variation:
第二个变化:
function temporarySwapHalf(array)
{
var left = null;
var right = null;
var length = array.length;
for (left = 0; left < length / 2; left += 1)
{
right = length - 1 - left;
var temporary = array[left];
array[left] = array[right];
array[right] = temporary;
}
return array;
}
XOR swap:
异或交换:
First variation:
第一个变化:
function xorSwap(array)
{
var i = null;
var r = null;
var length = array.length;
for (i = 0, r = length - 1; i < r; i += 1, r -= 1)
{
var left = array[i];
var right = array[r];
left ^= right;
right ^= left;
left ^= right;
array[i] = left;
array[r] = right;
}
return array;
}
Second variation:
第二个变化:
function xorSwapHalf(array)
{
var i = null;
var r = null;
var length = array.length;
for (i = 0; i < length / 2; i += 1)
{
r = length - 1 - i;
var left = array[i];
var right = array[r];
left ^= right;
right ^= left;
left ^= right;
array[i] = left;
array[r] = right;
}
return array;
}
There is another swap method called destructuring assignment: http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
还有另一种称为解构赋值的交换方法:http: //wiki.ecmascript.org/doku.php?id=harmony:destructuring
Destructuring assignment:
解构赋值:
First variation:
第一个变化:
function destructuringSwap(array)
{
var left = null;
var right = null;
var length = array.length;
for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
{
[array[left], array[right]] = [array[right], array[left]];
}
return array;
}
Second variation:
第二个变化:
function destructuringSwapHalf(array)
{
var left = null;
var right = null;
var length = array.length;
for (left = 0; left < length / 2; left += 1)
{
right = length - 1 - left;
[array[left], array[right]] = [array[right], array[left]];
}
return array;
}
Right now, an algorithm using destructuring assignment is the slowest of them all. It is even slower than Array.reverse();
. However, the algorithms using destructuring assignments and Array.reverse();
methods are the shortest examples, and they look the cleanest. I hope their performance gets better in the future.
目前,使用解构赋值的算法是所有算法中最慢的。它甚至比Array.reverse();
. 然而,使用解构赋值和Array.reverse();
方法的算法是最短的例子,它们看起来最干净。我希望他们的表现在未来变得更好。
Another mention is that modern browsers are improving their performance of array push
and splice
operations.
另一个提到的是现代浏览器正在提高其数组push
和splice
操作的性能。
In Firefox 10, this for
loop algorithm using array push
and splice
rivals the temporary swap and XOR swap loop algorithms.
在 Firefox 10 中,这种for
使用数组的循环算法可以push
与splice
临时交换和 XOR 交换循环算法相媲美。
for (length -= 2; length > -1; length -= 1)
{
array.push(array[length]);
array.splice(length, 1);
}
However, you should probably stick with the swap loop algorithms until many of the other browsers match or exceed their array push
and splice
performance.
但是,您可能应该坚持使用交换循环算法,直到许多其他浏览器匹配或超过它们的数组push
和splice
性能。
回答by Raynos
Native methods are always faster.
本机方法总是更快。
So use Array.reverse
where possible. Otherwise an implementation that runs in O(1)
would be best ;)
所以Array.reverse
尽可能使用。否则运行的实现O(1)
将是最好的;)
Otherwise just use something like this
否则就使用这样的东西
var reverse = function(arr) {
var result = [],
ii = arr.length;
for (var i = ii - 1;i !== 0;i--) {
result.push(arr[i]);
}
return result;
}
Interesting the loop is faster if you use all three stages of the for
construct instead of only one.
如果您使用for
构造的所有三个阶段而不是仅一个阶段,那么有趣的循环会更快。
for(var i = ii - 1; i !== 0;i--)
is faster then var i = ii - 1;for(;i-- !== 0;)
for(var i = ii - 1; i !== 0;i--)
然后更快 var i = ii - 1;for(;i-- !== 0;)
回答by Srinivas Damam
In simple way you can do this using map.
以简单的方式,您可以使用地图来做到这一点。
let list = [10, 20, 30, 60, 90]
let reversedList = list.map((e, i, a)=> a[(a.length -1) -i]) // [90, 60...]
回答by starwed
I opened a Firefox bugabout slow reverse performance in Firefox. Someone from Mozilla looked at the benchmark used in the accepted post, and says that it is pretty misleading -- in their analysis the native method is better in general for reversing arrays. (As it should be!)
我在 Firefox 中打开了一个关于缓慢反向性能的 Firefox 错误。Mozilla 的某个人查看了接受的帖子中使用的基准测试,并说它非常具有误导性——在他们的分析中,本机方法通常更适合反转数组。(理应如此!)
回答by CodeManX
Since no one came up with it and to complete the list of ways to reverse an array...
由于没有人想出它并完成反转数组的方法列表......
array.sort(function() {
return 1;
})
It's twice as fast as both while-approaches, but other than that, horribly slow.
它的速度是两种 while-approaches 的两倍,但除此之外,速度非常慢。
回答by Brice Lin
Swap functions are the fastest. Here's a reverse function I wrote that is only slightly similar to the swap functions mentioned above but performs faster.
交换函数是最快的。这是我写的一个反向函数,它与上面提到的交换函数略有相似,但执行速度更快。
function reverse(array) {
var first = null;
var last = null;
var tmp = null;
var length = array.length;
for (first = 0, last = length - 1; first < length / 2; first++, last--) {
tmp = array[first];
array[first] = array[last];
array[last] = tmp;
}
}
You can find the benchmarking here http://jsperf.com/js-array-reverse-vs-while-loop/19
你可以在这里找到基准测试http://jsperf.com/js-array-reverse-vs-while-loop/19
回答by Arslan shakoor
This is the most efficient and clean way to reverse an array with the ternary operator.
这是使用三元运算符反转数组的最有效和最干净的方法。
function reverse(arr) {
return arr.length < 2 ? arr : [arr.pop()].concat(reverse(arr));
}
console.log(reverse([4, 3, 3, 1]));
回答by SlavCo Zute
Another suggestion, similar to the above, but using splice instead:
另一个建议,类似于上述,但使用 splice 代替:
var myArray=["one","two","three","four","five","six"];
console.log(myArray);
for(i=0;i<myArray.length;i++){
myArray.splice(i,0,myArray.pop(myArray[myArray.length-1]));
}
console.log(myArray);
回答by clamchoda
Here's a java example http://www.leepoint.net/notes-java/data/arrays/arrays-ex-reverse.htmlshowing how to reverse an array. Very easy to convert to javascript.
这是一个 java 示例http://www.leepoint.net/notes-java/data/arrays/arrays-ex-reverse.html显示如何反转数组。非常容易转换为javascript。
I would suggest using something that simply captures the time before the function is called, and after the function is called. Which ever takes the least time / clock cycles will be the fastest.
我建议使用一些简单地捕获函数调用之前和函数调用之后的时间的东西。花费最少时间/时钟周期的将是最快的。
回答by tarikakyol
If you want to copy a reversed version of an array and keep the original as it is:
如果要复制数组的反向版本并保持原样:
a = [0,1,2,3,4,5,6,7,8,9];
b = []
for(i=0;i<a.length;i++){
b.push(a.slice(a.length-i-1,a.length-i)[0])
}
Output of b:
b 的输出:
[ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]