이 기사는 JavaScript의 기본 기술에 속합니다. 우리는 두 개의 JS 배열을 결합/병합하는 다양한 일반적인 방법을 배우고 다양한 방법의 장점과 단점을 비교할 것입니다.
특정 시나리오를 살펴 보겠습니다.
코드 사본은 다음과 같습니다.
var q = [5, 5, 1, 9, 9, 6, 4, 5, 8];
var b = [ "tie", "mao", "csdn", "ren", "fu", "fei"];
분명히, 배열 q와 b의 간단한 스 플라이 싱의 결과는 다음과 같습니다.
코드 사본은 다음과 같습니다.
[의 뜻
5, 5, 5, 1, 9, 9, 6, 4, 5, 8,
"tie", "mao", "csdn", "ren", "fu", "fei"
]]
concat (..) 방법
가장 일반적인 사용법은 다음과 같습니다.
코드 사본은 다음과 같습니다.
var c = q.concat (b);
큐; // [5,5,1,9,6,4,5,8]
비; // [ "tie", "mao", "csdn", "ren", "fu", "fei"];
기음; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
보시다시피, C는 Q와 B의 두 배열의 조합을 나타내는 새로운 배열이지만 Q와 B는 이제 쓸모가 없습니까?
Q 어레이에 10,000 개의 요소가 있고 B 어레이에는 10,000 개의 요소가있는 경우? 그런 다음 배열 C에는 이제 20,000 개의 요소가있어 메모리의 두 배를 차지합니다.
"이것은 괜찮습니다!"라고 생각할 수도 있습니다. Q와 B를 헛되게 넣으면 쓰레기가 수집 될 것입니다. 문제가 해결되었습니다!
코드 사본은 다음과 같습니다.
q = b = null; //`Q`와`B`는 이제 쓰레기를 수집 할 수 있습니다
음? 배열이 작 으면 자연스럽게 문제가 없습니다. 그러나 큰 배열 또는 반복 처리가 필요한 경우 메모리가 제한되어 있으며 최적화해야합니다.
루프 삽입
자, 배열#push () 메소드를 사용하여 배열의 내용을 다른 배열에 추가 해 보겠습니다.
코드 사본은 다음과 같습니다.
// 배열`b`를`q`에 삽입하십시오
for (var i = 0; i <b.length; i ++) {
Q.push (b [i]);
}
큐; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
b = null;
이제 두 개의 원래 배열의 내용은 Q (Q + B)에 저장됩니다.
메모리 최적화의 좋은 일을 한 것 같습니다.
그러나 Q 어레이가 매우 작고 B가 매우 큰 경우 어떻게해야합니까? 메모리 및 속도 고려 사항의 경우 더 작은 Q를 B 앞쪽에 삽입하려고합니다. 문제 없습니다. Push () 대신 Unshift () 메소드를 사용하면 해당 트래버스가 큰에서 작은 것으로 수행되어야합니다.
코드 사본은 다음과 같습니다.
//`Q`는`b`에 :
for (var i = q.length-1; i> = 0; i-) {
B. 시프트 (Q [I]);
}
비; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
q = null;
실용적인 팁
슬프게도, for 루프는 소박하고 유지하기가 어렵습니다. 우리가 더 잘 할 수 있습니까?
먼저 배열#을 시도해 봅시다.
코드 사본은 다음과 같습니다.
//`q 'on`Q` :
q = B.Reduce (function (coll, item) {
coll.push (항목);
Coll 리턴;
}, q);
큐; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
// 또는`q`에`b`에 :
b = q.reduceright (function (coll, item) {
coll.unshift (항목);
Coll 리턴;
}, b);
비; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
Array#Reduce () 및 Array#reduceRight ()는 매우 높은 엔드이지만 약간 부피가 크며 대부분의 사람들은 그것을 기억할 수 없습니다. JS 사양 6의 => 화살표 함수 (화살표 기능)는 코드의 양을 크게 줄일 수 있지만 각 배열 요소에 대한 기능 호출이 필요합니다. 이는 매우 나쁜 방법입니다.
그렇다면 다음 코드는 어떻습니까?
코드 사본은 다음과 같습니다.
//`q 'on`Q` :
Q.push.Apply (Q, B);
큐; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
// 또는`q`에`b`에 :
b.unshift.apply (b, q);
비; // [5,5,1,9,6,4,5,8, "Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"]
큰 것이 더 높습니다! 특히, unshift () 메소드는 이전과 같이 반대 순서를 고려할 필요가 없습니다. ES6의 확장 연산자 (스프레드 연산자, 접두사)가 더욱 발전되었습니다 : A.push (... B) 또는 B.unshift (... a)
그러나 실제로이 방법은 여전히 너무 낙관적입니다. 두 경우 모두, A 또는 B를 적용하여 ()를 제 2 매개 변수로 전달하는지 (첫 번째 매개 변수는 적용 메소드, 즉 컨텍스트, 스코프) 또는 ... 확장 연산자 메소드에서 내부적으로 내부적으로됩니다. 배열은 실제로 함수의 인수로 나뉩니다.
첫 번째 주요 문제는 배열이 함수 스택에 복사되어야하기 때문에 메모리의 두 배를 차지한다는 것입니다 (물론 임시!). 또한, 다른 JS 엔진마다 구현 알고리즘이 다르므로 기능이 전달할 수있는 매개 변수 수를 제한 할 수 있습니다.
배열이 백만 요소를 추가하면 푸시 () 또는 Unshift () 호출이든 함수 스택에서 허용되는 크기를 확실히 초과합니다. 이 방법은 수천 가지 요소가있을 때만 사용할 수 있으므로 특정 범위를 초과하는 것으로 제한되어야합니다.
참고 : Splice ()를 시도 할 수 있으며 Push (..)/unshift (..)와 동일한 제한이 있음을 분명히 알 수 있습니다.
한 가지 옵션은이 방법을 계속 사용하는 것이지만 배치 처리는 다음과 같습니다.
코드 사본은 다음과 같습니다.
함수 combineInto (q, b) {
var len = q.length;
for (var i = 0; i <len; i = i+5000) {
// 한 번에 5,000 개의 항목이 처리됩니다
b.unshift.apply (b, q.slice (i, i+5000));
}
}
잠깐, 우리는 코드의 가독성을 손상시킵니다 (심지어 성능!). 우리가 포기하기 전에이 여정을 끝내십시오.
요약
Array#concat ()은 두 개의 (또는 그 이상) 배열을 결합하기위한 시도되고 테스트 된 방법입니다. 그러나 그는 기존 배열을 수정하는 대신 새로운 배열을 만듭니다.
적응하는 방법에는 여러 가지가 있지만 모두 다른 장점과 단점이 있으며 실제 조건에 따라 선택해야합니다.
다양한 장점/단점이 위에 나열되어 있으며, 아마도 가장 좋은 방법 (나열되지 않은 방법 포함)은 감소 (..) 및 reduceRight (..)입니다.
당신이 선택하든, 당신은 당신의 조합과 전략에 대해 비판적으로 생각해야합니다.