Jaki jest najskuteczniejszy sposób konkatenacji tablic N?


Odpowiedzi:


323

Jeśli łączysz więcej niż dwie tablice, concat()jest to droga do wygody i prawdopodobnej wydajności.

var a = [1, 2], b = ["x", "y"], c = [true, false];
var d = a.concat(b, c);
console.log(d); // [1, 2, "x", "y", true, false];

W celu połączenia tylko dwóch tablic pushmożna użyć zamiast tego wielu argumentów składających się z elementów do dodania do tablicy, aby dodać elementy z jednej tablicy do końca drugiej bez tworzenia nowej tablicy. Dzięki slice()niemu można go również użyć zamiast, concat()ale wydaje się, że nie ma żadnej przewagi wydajności .

var a = [1, 2], b = ["x", "y"];
a.push.apply(a, b);
console.log(a); // [1, 2, "x", "y"];

W ECMAScript 2015 i nowszych wersjach można to jeszcze bardziej zmniejszyć

a.push(...b)

Wydaje się jednak, że w przypadku dużych tablic (rzędu 100 000 lub więcej elementów) technika przekazywania tablicy elementów do push(przy użyciu apply()lub operatora rozprzestrzeniania ECMAScript 2015) może się nie powieść. W przypadku takich tablic lepszym rozwiązaniem jest użycie pętli. Szczegółowe informacje można znaleźć na stronie https://stackoverflow.com/a/17368101/96100 .


1
a.concat(b)Wydaje mi się, że twój test może zawierać błąd: przypadek testowy wydaje się niepotrzebnie robić kopię tablicy, aa następnie ją wyrzucać.
ninjagecko

1
@ninjagecko: Masz rację. Zaktualizowałem go: jsperf.com/concatperftest/6 . W szczególnym przypadku tworzenia nowej tablicy, która łączy dwie istniejące tablice, wydaje się, że jest concat()ona ogólnie szybsza. W przypadku konkatenacji tablicy z istniejącą tablicą w miejscu, push()jest droga. Zaktualizowałem swoją odpowiedź.
Tim Down

16
Mogę zaświadczyć, że rozszerzenie pojedynczej tablicy o kilka nowych tablic przy użyciu metody push.apply zapewnia ogromną przewagę wydajności (~ 100x) w porównaniu z prostym wywołaniem konkat. Mam do czynienia z bardzo długimi listami krótkich list liczb całkowitych w v8 / node.js.
chbrown

1
Jeszcze bardziej zwięzłym sposobem jest a.push (... b);
dinvlad

1
@dinvlad: Prawda, ale tylko w środowiskach ES6. Do mojej odpowiedzi dodałem notatkę.
Tim Down

158
[].concat.apply([], [array1, array2, ...])

edycja : dowód wydajności: http://jsperf.com/multi-array-concat/7

edit2 : Tim Supinie wspomina w komentarzach, że może to spowodować, że interpreter przekroczy rozmiar stosu wywołań. Być może zależy to od silnika js, ale dostałem również „Przekroczono maksymalny rozmiar stosu wywołań” przynajmniej w Chrome. Przypadek testowy: [].concat.apply([], Array(300000).fill().map(_=>[1,2,3])). (Otrzymałem również ten sam błąd przy użyciu obecnie akceptowanej odpowiedzi, więc ktoś przewiduje takie przypadki użycia lub buduje bibliotekę dla innych, specjalne testy mogą być konieczne bez względu na wybrane rozwiązanie).


3
@ c69: wydaje się być tak samo skuteczny, jak wybrana odpowiedź wielokrotnie .push (#, #, ..., #), przynajmniej w Chrome. jsperf.com/multi-array-concat Wybrana odpowiedź przez Tim Down może również zawierać błąd. Ten link jest porównaniem wydajności łączenia wielu tablic jako zadane pytanie (nie tylko 2); testowanych jest wiele możliwych długości.
ninjagecko

IMO to najskuteczniejszy sposób na „scalenie” tablic, dobra robota
Eric Uldall,

Ta odpowiedź jest szczególnie przydatna, gdy N nie jest znane z góry, na przykład gdy masz tablicę o dowolnej długości i chcesz je wszystkie połączyć.
jfriend00

3
Z ES6 i operatorami rozprzestrzeniania staje się jeszcze prostsze: [] .concat (... [array1, array2, ...]) Cóż, drugie trzy kropki są trochę niefortunne. Pierwsze trzy to operator rozprzestrzeniania developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Eydrian

Eydrian: Osobiście staram się unikać operatora rozprzestrzeniania, ponieważ jest on bardzo nieefektywny, ale nie jestem jeszcze pewien, czy to dlatego, że implementacja jest niedojrzała, czy semantyka specyfikacji es6 wymaga nieco cięższego podnoszenia (tj. Nigdy nie będzie lepsza ). Nie uruchomiłem żadnych testów porównawczych w tym konkretnym przypadku.
ninjagecko

34

Dla osób używających ES2015 (ES6)

Możesz teraz używać składni spreadu do łączenia tablic:

const arr1 = [0, 1, 2],
      arr2 = [3, 4, 5];

const result1 = [...arr1, ...arr2]; // -> [0, 1, 2, 3, 4, 5]

// or...

const result2 = [...arr2, ...arr1]; // -> [3, 4, 5, 0, 1, 2]

Jak to jest wydajne? Z tego, co przetestowałem, jest to bardzo wolne w przypadku tablic zawierających obiekty, patrz: jsperf.com/array-concat-vs-array-push-vs-array-spread/1
hitautodestruct

28

Ta concat()metoda służy do łączenia dwóch lub więcej tablic. Nie zmienia istniejących tablic, zwraca tylko kopię połączonych tablic.

array1 = array1.concat(array2, array3, array4, ..., arrayN);

1
Czasami nienawidzę JavaScript za brak modyfikacji oryginalnej tablicy. 🙄
Vincent Hoch-Drei,

@ VincentHoch-Drei concatjest specjalnie używany do tworzenia nowych tablic bez mutowania oryginalnej tablicy. Jeśli chcesz zaktualizować array1, musisz użyćarray1.push(...array2, ...array3, ...array4)
adiga

24

Użyj Array.prototype.concat.apply do obsługi konkatenacji wielu tablic:

var resultArray = Array.prototype.concat.apply([], arrayOfArraysToConcat);

Przykład:

var a1 = [1, 2, 3],
    a2 = [4, 5],
    a3 = [6, 7, 8, 9];
Array.prototype.concat.apply([], [a1, a2, a3]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

1
Podoba mi się ten! Działa z łatwością ze zmienną liczbą tablic do łączenia. +1
Joel

14

Jeśli jesteś w trakcie przepuszczania wyniku przez mapę / filtr / sortowanie itp. I chcesz skonkatować tablicę tablic, możesz użyć reduce

let sorted_nums = ['1,3', '4,2']
  .map(item => item.split(','))   // [['1', '3'], ['4', '2']]
  .reduce((a, b) => a.concat(b))  // ['1', '3', '4', '2']
  .sort()                         // ['1', '2', '3', '4']

14

W przypadku tablicy wielu tablic i ES6 użyj

Array.prototype.concat(...arr);

Na przykład:

const arr = [[1, 2, 3], [4, 5, 6], [7, 8 ,9]];
const newArr = Array.prototype.concat(...arr);
// output: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

1
Ponadto można usunąć zduplikowane elementy za pomocą newArr = Array.from(new Set(newArr));.
Darius M.

Dlaczego w maszynopisie to się dzieje any[]? Pisanie jest tam - dziwne.
Simon_Weaver,

Jest to naprawdę okropnie nieefektywne przy większych woluminach tablic. jsperf.com/flatten-array-203948 [].concat.apply([], ...arr) działa znacznie lepiej na dużych woluminach.
colemars,

7

Teraz możemy łączyć wiele tablic za pomocą ES6 Spread. Zamiast używać concat()do konkatenacji tablic, spróbuj użyć składni rozproszonej, aby połączyć wiele tablic w jedną spłaszczoną tablicę. na przykład:

var a = [1,2];
var b = [3,4];
var c = [5,6,7];
var d = [...a, ...b, ...c];
// resulting array will be like d = [1,2,3,4,5,6,7]

5

rozwiązane w ten sposób.

let arr = [[1, 2], [3, 4], [5, 6]];
 console.log([].concat(...arr));

Idealne rozwiązanie.
nehem

4

Możesz użyć strony jsperf.com do porównania wydajności. Oto link do konkat .

Dodano porównanie między:

var c = a.concat(b);

i:

var c = [];
for (i = 0; i < a.length; i++) {
    c.push(a[i]);
}
for (j = 0; j < b.length; j++) {
    c.push(b[j]);
}

Drugi jest prawie 10 razy wolniejszy w chromie.


Możesz jednak użyć tego push.apply(), co wydaje się być szybsze niż concat()we wszystkich przeglądarkach oprócz Chrome. Zobacz moją odpowiedź.
Tim Down


3

Oto funkcja, dzięki której można połączyć wiele tablic

function concatNarrays(args) {
    args = Array.prototype.slice.call(arguments);
    var newArr = args.reduce( function(prev, next) {
       return prev.concat(next) ;
    });

    return newArr;
}

Przykład -

console.log(concatNarrays([1, 2, 3], [5, 2, 1, 4], [2,8,9]));

wyjdzie

[1,2,3,5,2,1,4,2,8,9]

2

Jeśli masz tablicę tablic i chcesz połączyć elementy w jedną tablicę, wypróbuj następujący kod (wymaga ES2015):

let arrOfArr = [[1,2,3,4],[5,6,7,8]];
let newArr = [];
for (let arr of arrOfArr) {
    newArr.push(...arr);
}

console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Lub jeśli lubisz programowanie funkcjonalne

let arrOfArr = [[1,2,3,4],[5,6,7,8]];
let newArr = arrOfArr.reduce((result,current)=>{
    result.push(...current);
    return result;
});

console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Lub jeszcze lepiej ze składnią ES5, bez operatora spreadu

var arrOfArr = [[1,2,3,4],[5,6,7,8]];
var newArr = arrOfArr.reduce((result,current)=>{
    return result.concat(current);
});
console.log(newArr);
//Output: [1,2,3,4,5,6,7,8];

Ten sposób jest przydatny, jeśli nie znasz nie. tablic w czasie kodowania.


2

Skróć za pomocą ES6.

new Set([].concat(...Array));

Powoduje to konkatację i unikalność wielu tablic;

Demo na codepen


robi, ale usuwa duplikaty .. co zrobić, jeśli nie chcę usuwać duplikatów tablic?
Krunal Shah

new Set()usuwa zduplikowane elementy. Po prostu to usuń. [].concat(...Array)
ronaldtgi

Chcę użyć nowego zestawu ([]. concat (... Array)); ale chcę też usunąć duplikaty wraz z nim w jednym wyrażeniu. Czy to możliwe ?
Krunal Shah

2

Scal tablicę za pomocą push:

const array1 = [2, 7, 4];
const array2 = [3, 5,9];
array1.push(...array2);
console.log(array1)

Korzystanie z operatora Concat and Spread:

const array1 = [1,2];
const array2 = [3,4];

// Method 1: Concat 
const combined1 = [].concat(array1, array2);

// Method 2: Spread
const combined2 = [...array1, ...array2];

console.log(combined1);
console.log(combined2);


1

gdzie „n” to pewna liczba tablic, może tablica tablic. . .

var answer = _.reduce (n, funkcja (a, b) {return a.concat (b)})



0

Spróbuj tego:

i=new Array("aaaa", "bbbb");
j=new Array("cccc", "dddd");

i=i.concat(j);

@reggie, oboje skopiowaliście z tego samego źródła;)
I.devries

nie, mam informacje w tym samym linku, co ty. ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/...
Jairo

tak ... Chyba mamy to z tego samego źródła: D
reggie

przynajmniej @JAiro zmieniło zawartość tablicy. @reggie nie. :)
dogbane

to samo, ważne jest, aby pomóc ludziom rozwiązać jego problemy :)
JAiro

0

jeśli tablice N są pobierane z bazy danych i nie są zakodowane na stałe, zrobię to w ten sposób za pomocą ES6

let get_fruits = [...get_fruits , ...DBContent.fruit];
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.