¿Cuál es la forma más eficiente de concatenar N arrays?

Respuestas:

323

Si está concatenando más de dos matrices, este concat()es el camino a seguir para mayor comodidad y rendimiento probable.

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

Para concatenar solo dos matrices, el hecho de que pushacepta múltiples argumentos que consisten en elementos para agregar a la matriz se puede usar en su lugar para agregar elementos de una matriz al final de otra sin producir una nueva matriz. Con slice()esto también se puede usar en lugar de, concat()pero parece que no hay una ventaja de rendimiento al hacerlo .

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

En ECMAScript 2015 y versiones posteriores, esto se puede reducir aún más a

a.push(...b)

Sin embargo, parece que para matrices grandes (del orden de 100,000 miembros o más), la técnica que pasa una matriz de elementos push(ya sea usando apply()o el operador de propagación ECMAScript 2015) puede fallar. Para tales matrices, usar un bucle es un mejor enfoque. Consulte https://stackoverflow.com/a/17368101/96100 para más detalles.

Tim Down
fuente
1
Creo que su prueba puede tener un error: el a.concat(b)caso de prueba parece estar haciendo innecesariamente una copia de la matriz y aluego tirarla.
ninjagecko
1
@ninjagecko: Tienes razón. Lo actualicé: jsperf.com/concatperftest/6 . Para el caso particular de crear una nueva matriz que concatena dos matrices existentes, parece concat()que generalmente es más rápido. Para el caso de concatenar una matriz en una matriz existente en su lugar, push()es el camino a seguir. Actualicé mi respuesta.
Tim Down
16
Puedo dar fe de que extender una sola matriz con varias matrices nuevas usando el método push.apply confiere una gran ventaja de rendimiento (~ 100x) sobre la simple llamada concat. Estoy tratando con listas muy largas de listas cortas de enteros, en v8 / node.js.
chbrown
1
Una forma aún más concisa es a.push (... b);
dinvlad
1
@dinvlad: Verdadero, pero solo en entornos ES6. He agregado una nota a mi respuesta.
Tim Down
158
[].concat.apply([], [array1, array2, ...])

editar : prueba de eficiencia: http://jsperf.com/multi-array-concat/7

edit2 : Tim Supinie menciona en los comentarios que esto puede causar que el intérprete exceda el tamaño de la pila de llamadas. Esto quizás dependa del motor js, pero también obtuve el "Tamaño máximo de pila de llamadas excedido" en Chrome al menos. Caso de prueba: [].concat.apply([], Array(300000).fill().map(_=>[1,2,3])). (También recibí el mismo error al usar la respuesta actualmente aceptada, por lo que uno está anticipando tales casos de uso o construyendo una biblioteca para otros, puede ser necesario realizar pruebas especiales sin importar la solución que elija).

ninjagecko
fuente
3
@ c69: parece tan eficiente como la respuesta elegida de repetidamente .push (#, #, ..., #), en Chrome al menos. jsperf.com/multi-array-concat La respuesta elegida por Tim Down también puede tener un error. Este enlace es una comparación de rendimiento de unir múltiples matrices como se hizo la pregunta (no solo 2); Se prueban múltiples longitudes posibles.
ninjagecko
OMI, esta es la forma más efectiva de "fusionar" n arrays, bien hecho
Eric Uldall
Esta respuesta es particularmente útil cuando N no se conoce con anticipación, como cuando tiene una matriz de matrices de longitud arbitraria y desea que todas se concatenen.
jfriend00
3
Con ES6 y los operadores de propagación se vuelve aún más simple: [] .concat (... [array1, array2, ...]) Bueno, los segundos tres puntos son un poco desafortunados. Los tres primeros son el operador de propagación developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Eydrian
Eydrian: Personalmente trato de evitar el operador de propagación porque es muy ineficiente, pero aún no estoy seguro si eso se debe a que la implementación es inmadura o si la semántica de la especificación es6 requiere un poco de trabajo pesado (es decir, nunca mejorará) ) Sin embargo, no he ejecutado ningún punto de referencia en este caso particular.
ninjagecko
34

Para personas que usan ES2015 (ES6)

Ahora puede usar la sintaxis de propagación para concatenar matrices:

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]
Duncan Luk
fuente
¿Qué tan eficiente es esto? Por lo que he probado, esto es muy lento para las matrices que contienen objetos, consulte: jsperf.com/array-concat-vs-array-push-vs-array-spread/1
hitautodestruct
28

El concat()método se usa para unir dos o más matrices. No cambia las matrices existentes, solo devuelve una copia de las matrices unidas.

array1 = array1.concat(array2, array3, array4, ..., arrayN);
dogbane
fuente
1
A veces odio JavaScript por no alterar la matriz original. 🙄
Vicente Hoch-Drei
@ VincentHoch-Drei concatse usa específicamente para crear nuevas matrices sin mutar la matriz original. Si desea actualizar array1, tendría que usararray1.push(...array2, ...array3, ...array4)
adiga
24

Use Array.prototype.concat.apply para manejar la concatenación de múltiples matrices:

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

Ejemplo:

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]
Burnee
fuente
1
¡Me gusta este! Funciona fácilmente con un número variable de matrices para concatenar. +1
Joel
14

Si está en medio de canalizar el resultado a través de map / filter / sort, etc. y desea concatenar una matriz de matrices, puede usar 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']
artnikpro
fuente
14

Para una matriz de múltiples matrices y ES6, use

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

Por ejemplo:

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 ]
David
fuente
1
Además, puede eliminar elementos duplicados mediante el uso newArr = Array.from(new Set(newArr));.
Darius M.
¿Por qué en mecanografiado se convierte esto any[]? El tipeo está ahí, raro.
Simon_Weaver
En realidad, esto es bastante ineficiente en grandes volúmenes de matriz. jsperf.com/flatten-array-203948 [].concat.apply([], ...arr) funciona mucho mejor en grandes volúmenes.
colemars
7

Ahora podemos combinar múltiples matrices usando ES6 Spread. En lugar de usar concat()para concatenar matrices, intente usar la sintaxis extendida para combinar múltiples matrices en una matriz aplanada. p.ej:

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]
chinmayan
fuente
5

resuelto así.

let arr = [[1, 2], [3, 4], [5, 6]];
 console.log([].concat(...arr));
Th1
fuente
Solución perfecta.
Nehem
4

Puede usar el sitio jsperf.com para comparar el rendimiento. Aquí hay un enlace a concat .

Comparación agregada entre:

var c = a.concat(b);

y:

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

El segundo es casi 10 veces más lento en cromo.

gor
fuente
Sin embargo, puede usar push.apply(), que parece ser más rápido que concat()en todos los navegadores, excepto Chrome. Mira mi respuesta.
Tim Down
3

Aquí hay una función por la cual puede concatenar múltiples números de matrices

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

    return newArr;
}

Ejemplo

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

saldrá

[1,2,3,5,2,1,4,2,8,9]
Koushik Das
fuente
3

Combinar matriz con Push:

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

Usando el operador Concat y 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);

Zobia Kanwal
fuente
2

Si tiene una matriz de matrices y desea concatenar los elementos en una sola matriz, intente con el siguiente código (Requiere 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 si te gusta la programación funcional

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 incluso mejor con la sintaxis ES5, sin el operador de propagación

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

Este camino es útil si no sabes el no. de matrices en el momento del código.

novato
fuente
2

Acortar con ES6.

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

Esto hace concat y único los múltiples arreglos;

Demo en codepen

ronaldtgi
fuente
lo hace pero elimina los duplicados ... ¿y si no quiero eliminar los arreglos duplicados?
Krunal Shah
new Set()elimina elementos duplicados. Solo quítalo. [].concat(...Array)
ronaldtgi
quiero usar el nuevo Set ([]. concat (... Array)); pero también quiero eliminar duplicados junto con él en una sola expresión. Es posible ?
Krunal Shah
1

donde 'n' es un número de matrices, tal vez una matriz de matrices. . .

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

rashadb
fuente
0

prueba esto:

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

i=i.concat(j);
JAiro
fuente
@reggie, ambos copiaron y pegaron de la misma fuente;)
I.devries
No, tengo que verificar la información en el mismo enlace que tú. ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/…
JAiro
sí ... supongo que lo obtuvimos de la misma fuente: D
reggie
al menos @JAiro cambió el contenido de la matriz. @reggie no lo hizo. :)
dogbane
es lo mismo, lo importante es ayudar a las personas a resolver sus problemas :)
JAiro
0

si las matrices N se obtienen de la base de datos y no están codificadas, lo haré así usando ES6

let get_fruits = [...get_fruits , ...DBContent.fruit];
Akinnifesi Damilola
fuente