Javascript에서 배열을 뒤집는 가장 효율적인 방법은 무엇입니까?
최근 Javascript에서 배열을 뒤집는 가장 효율적인 방법이 무엇인지 물었습니다. 지금은 for 루프를 사용하고 배열을 다루도록 제안했지만 네이티브 Array.reverse()
메서드 가 있음을 깨달았습니다 .
호기심을 위해, 누군가 내가 이것을 읽을 수 있도록 예제를 보여 주거나 올바른 방향을 가리킴으로써 이것을 탐구하도록 도울 수 있습니까? 성능을 측정하는 방법에 대한 제안도 훌륭합니다.
이 설정을 기반으로 :
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var length = array.length;
Array.reverse();
첫 번째 또는 두 번째로 느립니다!
벤치 마크는 다음과 같습니다. http://jsperf.com/js-array-reverse-vs-while-loop/5
브라우저에서 스왑 루프가 더 빠릅니다. 두 가지 일반적인 유형의 스왑 알고리즘 ( Wikipedia 참조 )이 있으며 각각 두 가지 변형이 있습니다.
두 가지 유형의 스왑 알고리즘은 임시 스왑과 XOR 스왑입니다.
두 변형은 인덱스 계산을 다르게 처리합니다. 첫 번째 변형은 현재 왼쪽 인덱스와 오른쪽 인덱스를 비교 한 다음 배열의 오른쪽 인덱스를 감소시킵니다. 두 번째 변형은 현재 왼쪽 인덱스와 길이를 절반으로 나눈 값을 비교 한 다음 각 반복에 대해 오른쪽 인덱스를 다시 계산합니다.
두 변형 사이에 큰 차이가있을 수도 있고 그렇지 않을 수도 있습니다. 예를 들어 Chrome 18에서 임시 스왑 및 XOR 스왑의 첫 번째 변형은 두 번째 변형보다 60 % 이상 느리지 만 Opera 12에서는 임시 스왑과 XOR 스왑의 두 변형 모두 유사한 성능을 보입니다.
임시 스왑 :
첫 번째 변형 :
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;
}
두 번째 변형 :
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 스왑 :
첫 번째 변형 :
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;
}
두 번째 변형 :
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;
}
Destructuring Assignment라는 또 다른 스왑 방법이 있습니다 : http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
구조 해제 할당 :
첫 번째 변형 :
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;
}
두 번째 변형 :
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;
}
지금은 구조 해제 할당을 사용하는 알고리즘이 가장 느립니다. 보다 느립니다 Array.reverse();
. 그러나 비 구조화 할당 및 Array.reverse();
방법을 사용하는 알고리즘 은 가장 짧은 예이며 가장 깔끔해 보입니다. 앞으로 그들의 실적이 좋아 졌으면 좋겠습니다.
또 다른 언급은 최신 브라우저가 어레이 push
및 splice
운영 성능을 개선하고 있다는 것 입니다.
Firefox 10에서 for
배열을 사용하는 이 루프 알고리즘 은 임시 스왑 및 XOR 스왑 루프 알고리즘 push
과 splice
경쟁합니다.
for (length -= 2; length > -1; length -= 1)
{
array.push(array[length]);
array.splice(length, 1);
}
그러나 다른 많은 브라우저가 어레이 push
및 splice
성능 과 일치하거나 초과 할 때까지 스왑 루프 알고리즘을 고수해야 합니다.
네이티브 메서드는 항상 더 빠릅니다.
따라서 Array.reverse
가능하면 사용 하십시오. 그렇지 않으면 실행되는 구현이 O(1)
가장 좋습니다.)
그렇지 않으면 다음과 같이 사용하십시오.
var reverse = function(arr) {
var result = [],
ii = arr.length;
for (var i = ii - 1;i !== 0;i--) {
result.push(arr[i]);
}
return result;
}
for
하나만 사용하는 대신 구성 의 세 단계를 모두 사용하면 루프가 더 빠릅니다 .
for(var i = ii - 1; i !== 0;i--)
더 빠르다 var i = ii - 1;for(;i-- !== 0;)
간단한 방법으로지도를 사용하여이를 수행 할 수 있습니다.
let list = [10, 20, 30, 60, 90]
let reversedList = list.map((e, i, a)=> a[(a.length -1) -i]) // [90, 60...]
나는 파이어 폭스 버그를 오픈 파이어 폭스에서 느린 역의 성능에 대해. Mozilla의 누군가가 승인 된 게시물에 사용 된 벤치 마크를 살펴 보았고 이는 상당히 오해의 소지가 있다고 말합니다. 분석에서 일반적으로 배열을 뒤집는 데 기본 방법이 더 좋습니다. (그렇게해야합니다!)
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.
http://jsperf.com/js-array-reverse-vs-while-loop/53
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
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]));
Here's a java example http://www.leepoint.net/notes-java/data/arrays/arrays-ex-reverse.html showing how to reverse an array. Very easy to convert to 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.
Another suggestion, similar to the above, but using splice instead:
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);
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:
[ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Here is another example to permanently modify the array reversing it's elements:
var theArray = ['a', 'b', 'c', 'd', 'e', 'f'];
function reverseArrayInPlace(array) {
for (var i = array.length - 1; i >= 0; i -= 1) {
array.push(array[i]);
}
array.splice(0, array.length / 2);
return array;
};
reverseArrayInPlace(theArray);
console.log(theArray); // -> ["f", "e", "d", "c", "b", "a"]
Here are a couple of tricks I found. Credit goes to Codemanx for the original solution of
array.sort(function() { return 1; })
In Typescript, this can be simplified to just one line
array.sort(() => 1)
var numbers = [1,4,9,13,16];
console.log(numbers.sort(() => 1));
Since this will be the future of JavaScript, I thought I'd share that.
Here's another trick if your array only has 2 elements
array.push(array.shift());
I found a simple way to do this with .slice().reverse()
var yourArray = ["first", "second", "third", "...", "etc"]
var reverseArray = yourArray.slice().reverse()
console.log(reverseArray)
You will get
["etc", "...", "third", "second", "first"]
You could also make use of reduceRight
which will iterate through each value of the array (from right-to-left)
const myArray = [1, 2, 3, 4, 5]
const reversedArray = myArray.reduceRight((acc, curr) => [...acc, curr], [])
console.log(reversedArray) // [5, 4, 3, 2, 1]
Pasting the below into any javascript runtime console either on the browser or node.js would do a straight way benchmark test on a large array of number.
Say 40,000 in my case
var array = Array.from({ length: 40000 }, () =>
Math.floor(Math.random() * 40000)
);
var beforeStart = Date.now();
var reversedArray = array.map((obj, index, passedArray) => {
return passedArray[passedArray.length - index - 1];
});
console.log(reversedArray);
var afterCustom = Date.now();
console.log(array.reverse());
var afterNative = Date.now();
console.log(`custom took : ${afterCustom - beforeStart}ms`);
console.log(`native took : ${afterNative - afterCustom}ms`);
You can simply run the snippet directly to see how the custom version fare too.
ReferenceURL : https://stackoverflow.com/questions/5276953/what-is-the-most-efficient-way-to-reverse-an-array-in-javascript
'programing tip' 카테고리의 다른 글
jQuery를 사용하여 Span의 내용을 변경하는 방법은 무엇입니까? (0) | 2020.12.15 |
---|---|
할당 내 자바 스크립트 AND 연산자 (0) | 2020.12.15 |
목적 C에서 float를 다음 정수로 반올림합니까? (0) | 2020.12.15 |
Bash에서 if 문 산술을 어떻게 수행합니까? (0) | 2020.12.15 |
XML 주석 및 "-" (0) | 2020.12.15 |