Este artículo pertenece a las habilidades básicas de JavaScript. Aprenderemos varios métodos comunes para combinar/fusionar dos matrices JS y comparar las ventajas y desventajas de varios métodos.
Echemos un vistazo al escenario específico:
La copia del código es la siguiente:
var q = [5, 5, 1, 9, 9, 6, 4, 5, 8];
var b = ["TIE", "MAO", "CSDN", "Ren", "Fu", "Fei"];
Obviamente, el resultado del empalme simple de las matrices Q y B es:
La copia del código es la siguiente:
[
5, 5, 1, 9, 9, 6, 4, 5, 8,
"empate", "mao", "csdn", "ren", "fu", "fei"
]
método concat (..)
Los usos más comunes son los siguientes:
La copia del código es la siguiente:
var c = q.concat (b);
Q; // [5,5,1,9,9,6,4,5,8]
b; // ["Tie", "Mao", "CSDN", "Ren", "Fu", "Fei"];
do; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
Como puede ver, C es una matriz nueva que representa una combinación de dos matrices: Q y B, pero Q y B son inútiles ahora, ¿verdad?
Si la matriz Q tiene 10,000 elementos y la matriz B tiene 10,000 elementos? Entonces la matriz C ahora tiene 20,000 elementos, que ocupan el doble de la memoria.
"¡Esto está bien!", Pudes pensar. Simplemente ponga Q y B en vano, y luego se recolectará basura, ¿verdad? ¡El problema está resuelto!
La copia del código es la siguiente:
q = b = nulo; // `Q` y` B` ahora pueden ser basura
¿Um? Si las matrices son pequeñas, entonces naturalmente no hay problema. Sin embargo, cuando se requieren matrices grandes o procesamiento repetido, la memoria es limitada y también debe optimizarse.
Inserción de bucle
Ok, intentemos agregar el contenido de una matriz a otra, usando el método matriz#push ():
La copia del código es la siguiente:
// insertar matriz `b` en` Q`
para (var i = 0; i <b.length; i ++) {
q.push (b [i]);
}
Q; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
b = nulo;
Ahora, el contenido de dos matrices originales se almacenan en Q (Q + B).
Parece haber hecho un buen trabajo de optimización de memoria.
Pero, ¿qué pasa si la matriz Q es muy pequeña y B es muy grande? Para las consideraciones de memoria y velocidad, desea insertar la Q más pequeña en el frente de B. No hay problema, solo use el método unshift () en lugar de push (), y el recorrido correspondiente debe realizarse de gran a pequeño:
La copia del código es la siguiente:
// `Q` en` B`:
for (var i = q.length-1; i> = 0; i--) {
B.unshift (q [i]);
}
b; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
q = nulo;
Consejos prácticos
Lamentablemente, el bucle for es rústico y difícil de mantener. ¿Podemos hacerlo mejor?
Probemos la matriz#reducir primero:
La copia del código es la siguiente:
// `B` en` Q`:
Q = B.Reduce (función (coll, elemento) {
coll.push (elemento);
regresar coll;
}, q);
Q; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
// o `Q` en` B`:
b = Q.Reduceright (function (coll, item) {
coll.unshift (ítem);
regresar coll;
}, b );
b; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
Array#Reduce () y Matray#Reduceright () son de gama muy de alta gama, pero un poco voluminosas, y la mayoría de la gente no puede recordarlo. Las funciones de flecha => (Funciones de flecha) en la especificación JS 6 pueden reducir en gran medida la cantidad de código, pero requiere llamadas de función a cada elemento de matriz, que también es un método muy malo.
Entonces, ¿qué tal el siguiente código?
La copia del código es la siguiente:
// `B` en` Q`:
q.push.apply (q, b);
Q; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
// o `Q` en` B`:
B.unshift.Aply (b, q);
b; // [5,5,1,9,9,6,4,5,8, "empate", "Mao", "CSDN", "Ren", "Fu", "Fei"]]
¿Grande es más alto, ¿verdad? En particular, el método Unshift () no necesita considerar el orden opuesto como antes. El operador de expansión de ES6 (operador de propagación, prefijo) está más avanzado: A.Push (... b) o B.unshift (... a)
Sin embargo, de hecho, este método sigue siendo demasiado optimista. En ambos casos, ya sea pasar A o B para aplicar () como el segundo parámetro (el primer parámetro se convierte en esto internamente al llamar a la función en el método de aplicar, es decir, contexto, alcance), o el ...
El primer problema importante es que ocupa el doble de la memoria (¡por supuesto, temporal!) Porque la matriz debe copiarse en la pila de funciones. Además, diferentes motores JS tienen diferentes algoritmos de implementación, lo que puede limitar el número de parámetros que la función puede pasar.
Si una matriz agrega un millón de elementos, definitivamente excederá el tamaño permitido por la pila de funciones, ya sea una llamada push () o una llamada sin cambio (). Este método solo está disponible cuando hay unos pocos miles de elementos, por lo que debe limitarse a exceder un rango determinado.
Nota: También puede probar Splice (), y definitivamente encontrará que tiene la misma limitación que Push (..)/Unshift (..).
Una opción es continuar usando este método, pero con procesamiento por lotes:
La copia del código es la siguiente:
función combineInto (q, b) {
var len = q.length;
para (var i = 0; i <len; i = i+5000) {
// 5,000 elementos se procesan a la vez
b.unshift.apply (b, q.slice (i, i+5000));
}
}
Espera, comprometemos la legibilidad del código (¡incluso el rendimiento!). Termine este viaje antes de rendirnos.
Resumir
Array#concat () es un método probado y probado para combinar dos (o más) matrices. Pero crea una nueva matriz en lugar de modificar la existente.
Hay muchas maneras de adaptarse, pero todos tienen diferentes ventajas y desventajas y necesitan ser elegidos de acuerdo con las condiciones reales.
Las diversas ventajas/desventajas se enumeran anteriormente, y quizás los mejores métodos (incluidos los que no están en la lista) son Reduce (..) y Reduceright (..)
Independientemente de lo que elija, debe pensar críticamente sobre su combinación y estrategia en lugar de darlo por sentado.