Qual è il modo più efficiente per concatenare le matrici N?


Risposte:


323

Se stai concatenando più di due array, concat()è la strada da percorrere per praticità e prestazioni probabili.

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];

Per concatenare solo due array, è possibile utilizzare il fatto che pushaccetta più argomenti costituiti da elementi da aggiungere all'array per aggiungere elementi da un array alla fine di un altro senza produrre un nuovo array. Con slice()esso può anche essere usato al posto di concat()ma non sembra esserci alcun vantaggio in termini di prestazioni .

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

In ECMAScript 2015 e versioni successive, questo può essere ulteriormente ridotto

a.push(...b)

Tuttavia, sembra che per array di grandi dimensioni (dell'ordine di 100.000 membri o più), la tecnica che passa una serie di elementi a push(utilizzando apply()o l'operatore di diffusione ECMAScript 2015) potrebbe non riuscire. Per tali array, l'uso di un loop è un approccio migliore. Per maggiori dettagli, consultare https://stackoverflow.com/a/17368101/96100 .


1
Credo che il tuo test possa avere un errore: il a.concat(b)test case sembra fare inutilmente una copia dell'array e apoi buttarlo via.
ninjagecko,

1
@ninjagecko: hai ragione. L'ho aggiornato: jsperf.com/concatperftest/6 . Nel caso particolare della creazione di un nuovo array che concatena due array esistenti, sembra concat()generalmente più veloce. Nel caso di concatenare un array su un array esistente, push()è la strada da percorrere. Ho aggiornato la mia risposta.
Tim Down

16
Posso attestare che l'estensione di un singolo array con diversi nuovi array utilizzando il metodo push.apply conferisce un enorme vantaggio in termini di prestazioni (~ 100x) rispetto alla semplice chiamata concat. Ho a che fare con elenchi molto lunghi di brevi elenchi di numeri interi, in v8 / node.js.
Chbrown

1
Un modo ancora più conciso è a.push (... b);
dinvlad,

1
@dinvlad: vero, ma solo in ambienti ES6. Ho aggiunto una nota alla mia risposta.
Tim Down il

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

modifica : prova di efficienza: http://jsperf.com/multi-array-concat/7

edit2 : Tim Supinie menziona nei commenti che ciò potrebbe far sì che l'interprete superi la dimensione dello stack di chiamate. Questo dipende forse dal motore js, ma ho almeno ottenuto "Dimensione massima dello stack di chiamate superata" su Chrome almeno. Test case: [].concat.apply([], Array(300000).fill().map(_=>[1,2,3])). (Ho anche ottenuto lo stesso errore utilizzando la risposta attualmente accettata, quindi uno sta anticipando tali casi d'uso o costruendo una libreria per altri, potrebbero essere necessari test speciali, indipendentemente dalla soluzione scelta.)


3
@ c69: sembra altrettanto efficace della risposta scelta ripetutamente .push (#, #, ..., #), almeno su Chrome. jsperf.com/multi-array-concat La risposta scelta da Tim Down potrebbe anche contenere un errore. Questo collegamento è un confronto delle prestazioni di unire più array come la domanda posta (non solo 2); vengono testate più lunghezze possibili.
ninjagecko,

IMO questo è il modo più efficace per "unire" n array, ben fatto
Eric Uldall

Questa risposta è particolarmente utile quando N non è noto in anticipo, ad esempio quando si dispone di una matrice di array di lunghezza arbitraria e si desidera che siano tutti concatenati.
jfriend00,

3
Con ES6 e gli operatori di diffusione diventa ancora più semplice: [] .concat (... [array1, array2, ...]) Bene, i secondi tre punti sono un po 'sfortunati. I primi tre sono l'operatore spread developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Eydrian,

Eydrian: personalmente cerco di evitare l'operatore di spread perché è molto inefficiente, ma non sono ancora sicuro se questo perché l'implementazione è immatura, o la semantica della specifica es6 richiede un po 'di sollevamento più pesante (cioè non migliorerà mai ). Non ho eseguito alcun benchmark in questo caso particolare però.
ninjagecko,

34

Per le persone che utilizzano ES2015 (ES6)

È ora possibile utilizzare la sintassi diffusa per concatenare le matrici:

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]

Quanto è efficiente questo? Da quello che ho testato è molto lento per gli array che contengono oggetti, vedere: jsperf.com/array-concat-vs-array-push-vs-array-spread/1
hitautodestruct

28

Il concat()metodo viene utilizzato per unire due o più array. Non modifica le matrici esistenti, restituisce solo una copia delle matrici unite.

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

1
A volte odio JavaScript per non aver modificato l'array originale. 🙄
Vincent Hoch-Drei l'

@ VincentHoch-Drei concatè utilizzato specificamente per creare nuovi array senza mutare l'array originale. Se vuoi aggiornare array1, dovresti usarearray1.push(...array2, ...array3, ...array4)
adiga l'

24

Utilizzare Array.prototype.concat.apply per gestire la concatenazione di più array:

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

Esempio:

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
Mi piace questa! Funziona facilmente con un numero variabile di matrici da concatenare. +1
Gioele,

14

Se si sta effettuando il piping del risultato tramite mappa / filtro / ordinamento ecc. E si desidera concaticare un array di array, è possibile utilizzare 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

Per array di più array ed ES6, utilizzare

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

Per esempio:

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
Inoltre puoi rimuovere elementi duplicati usando newArr = Array.from(new Set(newArr));.
Darius M.

Perché in dattiloscritto diventa any[]? La digitazione è lì - strana.
Simon_Weaver,

Questo è in realtà orribilmente inefficiente con volumi di array più grandi. jsperf.com/flatten-array-203948 ha [].concat.apply([], ...arr) prestazioni decisamente migliori a grandi volumi.
Colemars,

7

Ora possiamo combinare più array usando ES6 Spread. Invece di utilizzare concat()per concatenare le matrici, provare a utilizzare la sintassi di diffusione per combinare più matrici in un array appiattito. per esempio:

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

risolto in questo modo.

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

Soluzione perfetta
Nehem,

4

È possibile utilizzare il sito jsperf.com per confrontare le prestazioni. Ecco il link per concat .

Aggiunto confronto tra:

var c = a.concat(b);

e:

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

Il secondo è quasi 10 volte più lento in cromo.


Tuttavia, è possibile utilizzare push.apply(), che sembra essere più veloce rispetto concat()a tutti i browser tranne Chrome. Vedi la mia risposta
Tim Down


3

Ecco una funzione mediante la quale è possibile concatenare un numero multiplo di matrici

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

    return newArr;
}

Esempio -

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

uscirà

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

3

Unisci array con push:

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

Utilizzo dell'operatore 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);


2

Se si dispone di un array di array e si desidera concatenare gli elementi in un singolo array, provare il seguente codice (richiede 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];

O se ti piace la programmazione funzionale

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];

O ancora meglio con la sintassi ES5, senza l'operatore di diffusione

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];

In questo modo è utile se non si conosce il no. di matrici al momento del codice.


2

Accorciare con ES6.

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

Questo fa concat e unici gli array multipli;

Demo su codepen


lo fa ma rimuove i duplicati .. cosa succede se non desidero rimuovere gli array duplicati?
Krunal Shah,

new Set()rimuove gli elementi duplicati. Basta rimuoverlo. [].concat(...Array)
ronaldtgi,

voglio usare il nuovo Set ([]. concat (... Array)); ma voglio anche rimuovere i duplicati con esso in una singola espressione. È possibile ?
Krunal Shah,

1

dove 'n' è un numero di array, forse un array di array. . .

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



0

prova questo:

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

i=i.concat(j);

@reggie, entrambi incollati e copiati dalla stessa fonte;)
I.devries

no Ho controllato le informazioni nello stesso link che hai tu. ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/…
JAiro

sì ... immagino che l'abbiamo ottenuto dalla stessa fonte: D
reggie,

almeno @JAiro ha modificato il contenuto dell'array. @reggie no. :)
dogbane,

è lo stesso, l'importante è aiutare le persone a risolvere i suoi problemi :)
JAiro,

0

se gli array N sono ricavati dal database e non sono codificati, lo farò in questo modo usando ES6

let get_fruits = [...get_fruits , ...DBContent.fruit];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.