Qual é a maneira mais eficiente de concatenar matrizes N?

Respostas:

323

Se você concatenar mais de duas matrizes, concat()é o caminho a seguir para conveniência e desempenho provável.

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 apenas duas matrizes, o fato de pushaceitar vários argumentos que consistem em elementos a serem adicionados à matriz pode ser usado para adicionar elementos de uma matriz ao final de outra sem produzir uma nova matriz. Com slice()ele também pode ser usado em vez de, concat()mas parece não haver vantagem de desempenho ao fazer isso .

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

No ECMAScript 2015 e posterior, isso pode ser reduzido ainda mais para

a.push(...b)

No entanto, parece que, para matrizes grandes (da ordem de 100.000 membros ou mais), a técnica que envia uma matriz de elementos para push(usando apply()ou o operador de propagação ECMAScript 2015) pode falhar. Para essas matrizes, usar um loop é uma abordagem melhor. Consulte https://stackoverflow.com/a/17368101/96100 para obter detalhes.

Tim Down
fonte
1
Acredito que seu teste pode ter um erro: o a.concat(b)caso de teste parece desnecessariamente fazer uma cópia da matriz e adepois jogá-la fora.
Ninjagecko
1
@ ninjagecko: Você está certo. Eu atualizei: jsperf.com/concatperftest/6 . Para o caso específico de criar uma nova matriz que concatena duas matrizes existentes, ela concat()geralmente é mais rápida. No caso de concatenar uma matriz em uma matriz existente, push()é o caminho a percorrer. Eu atualizei minha resposta.
Tim Baixo
16
Eu posso atestar que estender uma única matriz com várias novas matrizes usando o método push.apply confere uma enorme vantagem de desempenho (~ 100x) sobre a simples chamada concat. Estou lidando com listas muito longas de listas curtas de números inteiros, na v8 / node.js.
21812 chbrown
1
Uma maneira ainda mais concisa é a.push (... b);
dinvlad
1
@dinvlad: Verdade, mas apenas em ambientes ES6. Eu adicionei uma nota à minha resposta.
Tim Baixo
158
[].concat.apply([], [array1, array2, ...])

edit : prova de eficiência: http://jsperf.com/multi-array-concat/7

edit2 : Tim Supinie menciona nos comentários que isso pode fazer com que o intérprete exceda o tamanho da pilha de chamadas. Talvez isso dependa do mecanismo js, ​​mas também recebi "Tamanho máximo da pilha de chamadas excedido" no Chrome. Caso de teste: [].concat.apply([], Array(300000).fill().map(_=>[1,2,3])). (Também obtive o mesmo erro ao usar a resposta atualmente aceita; portanto, se você está antecipando esses casos de uso ou construindo uma biblioteca para outros, testes especiais podem ser necessários, independentemente da solução escolhida.)

ninjagecko
fonte
3
@ c69: parece tão eficiente quanto a resposta escolhida de repetidamente .push (#, #, ..., #), pelo menos no Chrome. jsperf.com/multi-array-concat A resposta escolhida por Tim Down também pode ter um erro. Esse link é uma comparação de desempenho da união de várias matrizes conforme a pergunta (não apenas 2); vários comprimentos possíveis são testados.
Ninjagecko
IMO, esta é a maneira mais eficaz de "mesclar" n matrizes, bem feito #
Eric Uldall
Essa resposta é particularmente útil quando N não é conhecido antecipadamente, como quando você tem uma matriz de matrizes de comprimento arbitrário e deseja que todas sejam concatenadas.
precisa saber é
3
Com o ES6 e os operadores spread, fica ainda mais simples: [] .concat (... [array1, array2, ...]) Bem, os três últimos pontos são um pouco infelizes. Os três primeiros são o operador de propagação developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Eydrian
Eydrian: Eu pessoalmente tento evitar o operador de propagação porque é muito ineficiente, mas ainda não tenho certeza se é porque a implementação é imatura, ou a semântica da especificação es6 exige um pouco de levantamento mais pesado (ou seja, nunca ficará melhor ) Ainda não executamos nenhum benchmark nesse caso em particular.
Ninjagecko
34

Para pessoas que usam o ES2015 (ES6)

Agora você pode usar a sintaxe de propagação para concatenar matrizes:

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
fonte
Quão eficiente é isso? Pelo que testei, isso é muito lento para matrizes que contêm objetos, consulte: jsperf.com/array-concat-vs-array-push-vs-array-spread/1
hitautodestruct
28

O concat()método é usado para unir duas ou mais matrizes. Ele não altera as matrizes existentes, retorna apenas uma cópia das matrizes unidas.

array1 = array1.concat(array2, array3, array4, ..., arrayN);
dogbane
fonte
1
Às vezes eu odeio JavaScript por não modificar a matriz original. 🙄
Vincent Hoch-Drei
@ VincentHoch-Drei concaté usado especificamente para criar novas matrizes sem alterar a matriz original. Se você deseja atualizar array1, você teria que usararray1.push(...array2, ...array3, ...array4)
Adiga
24

Use Array.prototype.concat.apply para manipular a concatenação de várias matrizes:

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

Exemplo:

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
fonte
1
Eu gosto deste! Funciona facilmente com um número variável de matrizes para concatenar. +1
Joel
14

Se você estiver no meio da canalização do resultado através de map / filter / sort, etc, e quiser concaturar a matriz de matrizes, poderá 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
fonte
14

Para matriz de várias matrizes e ES6, use

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

Por exemplo:

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
fonte
1
Além disso, você pode remover elementos duplicados usando newArr = Array.from(new Set(newArr));.
Darius M.
Por que em texto datilografado isso se torna any[]? A digitação está lá - estranha.
Simon_Weaver 9/08/19
Na verdade, isso é terrivelmente ineficiente em volumes de matriz maiores. jsperf.com/flatten-array-203948 tem um [].concat.apply([], ...arr) desempenho muito melhor em grandes volumes.
Colemars 11/09/19
7

Agora podemos combinar várias matrizes usando ES6 Spread. Em vez de usar concat()para concatenar matrizes, tente usar a sintaxe de dispersão para combinar várias matrizes em uma matriz nivelada. por exemplo:

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
fonte
5

resolvido assim.

let arr = [[1, 2], [3, 4], [5, 6]];
 console.log([].concat(...arr));
Th1
fonte
Solução perfeita.
nehem 6/03
4

Você pode usar o site jsperf.com para comparar o desempenho. Aqui está o link para concat .

Adicionado comparação entre:

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

O segundo é quase 10 vezes mais lento no cromo.

gor
fonte
No entanto, você pode usar push.apply(), o que parece ser mais rápido do que concat()em todos os navegadores, exceto o Chrome. Veja minha resposta.
Tim Baixo
3

Aqui está uma função pela qual você pode concatenar vários números de matrizes

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

    return newArr;
}

Exemplo -

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

irá produzir

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

Se você possui uma matriz de matrizes e deseja concaturar os elementos em uma única matriz, tente o seguinte código (Requer 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];

Ou se você gosta de programação 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];

Ou ainda melhor com a sintaxe ES5, sem o operador spread

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

Dessa forma, é útil se você não souber o não. de matrizes no horário do código.

novato
fonte
2

Encurte com ES6.

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

Isso concat e único os vários arrays;

Demonstração no codepen

ronaldtgi
fonte
faz, mas remove duplicatas .. e se eu não quiser remover matrizes duplicadas?
Krunal Shah
new Set()remove itens duplicados. Apenas remova-o. [].concat(...Array)
ronaldtgi 18/06
Eu quero usar o novo Set ([]. concat (... Array)); mas também quero remover duplicatas junto com ela em uma única expressão. é possível ?
Krunal Shah
2

Mesclar matriz com push:

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

Usando o operador Concat e 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
fonte
1

onde 'n' é um número de matrizes, talvez uma matriz de matrizes. . .

var resposta = _.reduce (n, função (a, b) {retorna a.concat (b)})

rashadb
fonte
0

tente isto:

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

i=i.concat(j);
JAiro
fonte
@ reggie, vocês dois copiaram da mesma fonte;)
I.devries
não, verifique as informações no mesmo link que você. Você pode
usar o seguinte código
sim ... acho que conseguimos da mesma fonte: D
reggie 22/02
pelo menos @JAiro alterou o conteúdo da matriz. @ Reggie não. :)
dogbane
É a mesma coisa, o importante é ajudar as pessoas a resolver seus problemas :)
Jairo
0

se as matrizes N são obtidas do banco de dados e não codificadas, o farei assim usando o ES6

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