javascript 자바스크립트 - 자바 스크립트에서 배열을 복제하는 가장 빠른 방법-슬라이스 대 'for'루프




함수 복사 (14)

배열 복제

필자는 배열을 복제하는 데 걸리는 시간을 테스트하는 매우 간단한 유틸리티 함수를 만들었습니다. 100 % 신뢰할 수있는 것은 아니지만 기존 어레이를 복제하는 데 걸리는 시간을 일괄 적으로 알려줄 수 있습니다.

function clone(fn) {
    const arr = [...Array(1000000)];
    console.time('timer');
    fn(arr);
    console.timeEnd('timer');
}

그리고 테스트 된 다른 접근법 :

1)   5.79ms -> clone(arr => Object.values(arr));
2)   7.23ms -> clone(arr => [].concat(arr));
3)   9.13ms -> clone(arr => arr.slice());
4)  24.04ms -> clone(arr => { const a = []; for (let val of arr) { a.push(val); } return a; });
5)  30.02ms -> clone(arr => [...arr]);
6)  39.72ms -> clone(arr => JSON.parse(JSON.stringify(arr)));
7)  99.80ms -> clone(arr => arr.map(i => i));
8) 259.29ms -> clone(arr => Object.assign([], arr));
9) Maximum call stack size exceeded -> clone(arr => Array.of(...arr));

자바 스크립트에서 배열을 복제하려면 다음 중 빠른 것을 사용하십시오.

슬라이스 방식

var dup_array = original_array.slice();

For 루프

for(var i = 0, len = original_array.length; i < len; ++i)
   dup_array[i] = original_array[i];

두 가지 방법 모두 얕은 복사 만 수행합니다. original_array에 객체에 대한 참조가 포함되어 있으면 객체가 복제되지 않지만 참조 만 복사되므로 두 배열 모두 동일한 객체에 대한 참조를 갖게됩니다. 그러나 이것은이 질문의 요점이 아닙니다.

속도에 대해서만 묻고 있습니다.


다음을보십시오 : link . 그것은 속도가 아니라 편안함에 관한 것입니다. 게다가 볼 수 있듯이 원시 타입 에서만 slice (0) 를 사용할 수 있습니다 .

배열에 대한 참조 복사본이 아닌 배열의 독립 복사본을 만들려면 배열 슬라이스 메서드를 사용할 수 있습니다.

예:

배열에 대한 참조 복사본이 아닌 배열의 독립 복사본을 만들려면 배열 슬라이스 메서드를 사용할 수 있습니다.

var oldArray = ["mip", "map", "mop"];
var newArray = oldArray.slice();

개체를 복사하거나 복제하려면 :

function cloneObject(source) {
    for (i in source) {
        if (typeof source[i] == 'source') {
            this[i] = new cloneObject(source[i]);
        }
        else{
            this[i] = source[i];
  }
    }
}

var obj1= {bla:'blabla',foo:'foofoo',etc:'etc'};
var obj2= new cloneObject(obj1);

출처 : link


a.map(e => e) 은이 작업의 또 다른 대안입니다. 오늘 현재로는 .map() 이 Firefox에서 매우 빠릅니다 ( .slice(0) 만큼 .slice(0) . 그러나 Chrome에서는 그렇지 않습니다.

반면 배열이 다차원 인 경우 배열은 객체이고 객체는 참조 유형이므로 어떤 슬라이스 또는 연결 메서드도 치료법이 될 수 없습니다 ... 배열을 복제하는 올바른 방법 중 하나는 Array.prototype.clone() 은 다음과 같습니다.

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

var arr = [ 1, 2, 3, 4, [ 1, 2, [ 1, 2, 3 ], 4 , 5], 6 ],
    brr = arr.clone();
brr[4][2][1] = "two";
console.log(JSON.stringify(arr));
console.log(JSON.stringify(brr));


Spread 연산자로 ECMAScript 2015 방식 :

기본 예 :

var copyOfOldArray = [...oldArray]
var twoArraysBecomeOne = [...firstArray, ..seccondArray]

브라우저 콘솔에서 다음을 시도하십시오.

var oldArray = [1, 2, 3]
var copyOfOldArray = [...oldArray]
console.log(oldArray)
console.log(copyOfOldArray)

var firstArray = [5, 6, 7]
var seccondArray = ["a", "b", "c"]
var twoArraysBecomOne = [...firstArray, ...seccondArray]
console.log(twoArraysBecomOne);

참고 문헌


var cloned_array = [].concat(target_array);

그것은 배열의 길이에 따라 다릅니다. 배열 길이가 <= 1,000,000보다 작 으면 sliceconcat 메서드가 거의 같은 시간이 걸립니다. 그러나 당신이 더 넓은 범위를 줄 때, concat 방법이 이깁니다.

예를 들어 다음 코드를 시도하십시오.

var original_array = [];
for(var i = 0; i < 10000000; i ++) {
    original_array.push( Math.floor(Math.random() * 1000000 + 1));
}

function a1() {
    var dup = [];
    var start = Date.now();
    dup = original_array.slice();
    var end = Date.now();
    console.log('slice method takes ' + (end - start) + ' ms');
}

function a2() {
    var dup = [];
    var start = Date.now();
    dup = original_array.concat([]);
    var end = Date.now();
    console.log('concat method takes ' + (end - start) + ' ms');
}

function a3() {
    var dup = [];
    var start = Date.now();
    for(var i = 0; i < original_array.length; i ++) {
        dup.push(original_array[i]);
    }
    var end = Date.now();
    console.log('for loop with push method takes ' + (end - start) + ' ms');
}

function a4() {
    var dup = [];
    var start = Date.now();
    for(var i = 0; i < original_array.length; i ++) {
        dup[i] = original_array[i];
    }
    var end = Date.now();
    console.log('for loop with = method takes ' + (end - start) + ' ms');
}

function a5() {
    var dup = new Array(original_array.length)
    var start = Date.now();
    for(var i = 0; i < original_array.length; i ++) {
        dup.push(original_array[i]);
    }
    var end = Date.now();
    console.log('for loop with = method and array constructor takes ' + (end - start) + ' ms');
}

a1();
a2();
a3();
a4();
a5();

original_array의 길이를 1,000,000으로 설정하면 slice 메소드와 concat 메소드가 거의 동일한 시간 (임의의 숫자에 따라 3-4ms)이 소요됩니다.

original_array의 길이를 10,000,000으로 설정하면 slice 메서드가 60ms 이상 걸릴 수 있고 concat 메서드는 20ms 이상 걸립니다.


간단한 데모를 작성했습니다. http://jsbin.com/agugo3/edit

Internet Explorer 8의 결과는 156, 782 및 750이며,이 경우 slice 가 훨씬 빠름을 나타냅니다.


es6 방법은 어떨까요?

arr2 = [...arr1];


훨씬 깨끗한 해결책이 있습니다.

var srcArray = [1, 2, 3];
var clonedArray = srcArray.length === 1 ? [srcArray[0]] : Array.apply(this, srcArray);

Array 생성자는 정확히 하나의 인수로 호출 될 때 다르게 동작하므로 길이 검사가 필요합니다.


간단한 해결책 :

original = [1,2,3]
cloned = original.map(x=>x)

기술적으로 slice 가장 빠릅니다. 그러나 0 begin 인덱스를 추가하면 더 빠릅니다.

myArray.slice(0);

~보다 빠릅니다.

myArray.slice();

http://jsperf.com/cloning-arrays/3


깊은 복제를위한 가장 쉬운 방법 Array 또는 Object :

var dup_array = JSON.parse(JSON.stringify(original_array))

바닐라 JS : 세트와 같은 객체를 사용하여 중복 제거

객체에 넣고 키를 반복 할 수 있습니다.

function remove_duplicates(arr) {
    var obj = {};
    var ret_arr = [];
    for (var i = 0; i < arr.length; i++) {
        obj[arr[i]] = true;
    }
    for (var key in obj) {
        ret_arr.push(key);
    }
    return ret_arr;
}

바닐라 JS : 이미 본 값을 추적하여 중복 제거 (순서 안전)

또는 주문 안전 버전의 경우 객체를 사용하여 이전에 본 모든 값을 저장하고 배열에 추가하기 전에 값을 확인하십시오.

function remove_duplicates_safe(arr) {
    var seen = {};
    var ret_arr = [];
    for (var i = 0; i < arr.length; i++) {
        if (!(arr[i] in seen)) {
            ret_arr.push(arr[i]);
            seen[arr[i]] = true;
        }
    }
    return ret_arr;

}

ECMAScript 6 : 새로운 Set 데이터 구조 사용 (순서 안전)

ECMAScript 6에는 새로운 유형의 데이터 구조가 추가되어 모든 유형의 값을 저장할 수 있습니다. Set.values 는 요소를 삽입 순서로 반환합니다.

function remove_duplicates_es6(arr) {
    let s = new Set(arr);
    let it = s.values();
    return Array.from(it);
}

사용 예 :

a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]

c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]

d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]




javascript arrays duplicates copy slice