Este artigo pertence às habilidades básicas do JavaScript. Aprenderemos vários métodos comuns para combinar/mesclar duas matrizes JS e comparar as vantagens e desvantagens de vários métodos.
Vamos dar uma olhada no cenário específico:
A cópia do código é a seguinte:
var q = [5, 5, 1, 9, 9, 6, 4, 5, 8];
var b = ["tie", "mao", "csdn", "ren", "fu", "fei"];
Obviamente, o resultado de um splicing simples das matrizes Q e B é:
A cópia do código é a seguinte:
[[
5, 5, 1, 9, 9, 6, 4, 5, 8,
"tie", "mao", "csdn", "ren", "fu", "fei"
]
Método concat (..)
Os usos mais comuns são os seguintes:
A cópia do código é a seguinte:
var c = q.Concat (b);
q; // [5,5,1,9,9,6,4,5,8]
b; // ["tie", "mao", "csdn", "ren", "fu", "fei"];
c; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
Como você pode ver, C é uma nova matriz que representa uma combinação de duas matrizes: Q e B, mas Q e B são inúteis agora, certo?
Se a matriz Q tiver 10.000 elementos e a matriz B tem 10.000 elementos? Então a matriz C agora tem 20.000 elementos, que ocupa o dobro da memória.
"Está tudo bem!", Você pode pensar. Basta colocar Q e B em vão, e então será coletado de lixo, certo? O problema está resolvido!
A cópia do código é a seguinte:
q = b = nulo; // `q` e` b` agora podem ser coletados de lixo
Hum? Se as matrizes forem pequenas, naturalmente não há problema. No entanto, quando são necessárias grandes matrizes ou processamento repetido, a memória é limitada e também precisa ser otimizada.
Inserção de loop
Ok, vamos tentar adicionar o conteúdo de uma matriz a outra, usando o método da matriz#push ():
A cópia do código é a seguinte:
// Insira a matriz `b` em` q`
for (var i = 0; i <b.length; i ++) {
q.push (b [i]);
}
q; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
b = nulo;
Agora, o conteúdo de duas matrizes originais é armazenado em Q (Q + B).
Parece ter feito um bom trabalho de otimização da memória.
Mas e se a matriz Q for muito pequena e B for muito grande? Para considerações de memória e velocidade, você deseja inserir o q menor na frente de B. Não tem problema, basta usar o método não () em vez de push (), e a travessia correspondente deve ser realizada de grande a pequena:
A cópia do código é a seguinte:
// `q` em` b`:
for (var i = q.length-1; i> = 0; i--) {
B.UnShift (q [i]);
}
b; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
q = nulo;
Dicas práticas
Infelizmente, o loop for rústico e difícil de manter. Podemos fazer melhor?
Vamos tentar a matriz#reduzir primeiro:
A cópia do código é a seguinte:
// `b` em` q`:
Q = B.Reduce (função (coll, item) {
Coll.push (item);
retornar coll;
}, q);
q; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
// ou `q` em` b`:
b = q.RedUcerright (function (coll, item) {
Coll.unshift (item);
retornar coll;
}, b);
b; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
Array#Reduce () e Array#ReduceRight () são muito sofisticados, mas um pouco volumosos, e a maioria das pessoas não consegue se lembrar. As funções => seta (funções de seta) na especificação JS 6 podem reduzir bastante a quantidade de código, mas requer chamadas de função para cada elemento da matriz, o que também é um método muito ruim.
Então, e o código a seguir?
A cópia do código é a seguinte:
// `b` em` q`:
q.push.apply (q, b);
q; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
// ou `q` em` b`:
B.UnShift.Apply (B, Q);
b; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
Grande é mais alto, certo!? Em particular, o método não precisa considerar a ordem oposta como antes. O operador de expansão do ES6 (operador de spread, prefixo) é mais avançado: a.push (... b) ou b.unshift (... a)
No entanto, de fato, esse método ainda está muito otimista. Nos dois casos, seja aprovado a ou b para aplicar () como o segundo parâmetro (o primeiro parâmetro se torna internamente ao chamar a função no método Aplicar, ou seja, contexto, escopo) ou o ... método do operador de expansão, a matriz será realmente dividida nos argumentos da função.
O primeiro grande problema é que ele ocupa o dobro da memória (é claro, temporário!) Porque a matriz precisa ser copiada na pilha de funções. Além disso, diferentes motores JS têm diferentes algoritmos de implementação, o que pode limitar o número de parâmetros que a função pode passar.
Se uma matriz adicionar um milhão de elementos, ela definitivamente excederá o tamanho permitido pela pilha de funções, seja uma chamada push () ou uma não -definição (). Este método está disponível apenas quando existem alguns milhares de elementos, portanto, deve ser limitado para exceder um determinado intervalo.
Nota: Você também pode experimentar Splice () e definitivamente descobrirá que ela tem a mesma limitação que Push (..)/NEARFF (..).
Uma opção é continuar usando esse método, mas com processamento em lote:
A cópia do código é a seguinte:
Função CombineInto (q, b) {
var len = Q.Length;
for (var i = 0; i <len; i = i+5000) {
// 5.000 itens são processados por vez
B.UnShift.Apply (B, Q.Slice (i, i+5000));
}
}
Espere, comprometemos a legibilidade do código (até mesmo desempenho!). Terminar esta jornada antes de desistirmos.
Resumir
Array#concat () é um método testado e testado para combinar duas (ou mais) matrizes. Mas ele cria uma nova matriz em vez de modificar a existente.
Existem muitas maneiras de se adaptar, mas todas elas têm vantagens e desvantagens diferentes e precisam ser escolhidas de acordo com as condições reais.
As várias vantagens/desvantagens estão listadas acima, e talvez os melhores (incluindo os que não listados) são reduzidos (..) e reduteright (..)
O que você escolher, você deve pensar criticamente sobre sua combinação e estratégia, em vez de tomar isso como garantido.