No parece haber una manera de extender una matriz JavaScript existente con otra matriz, es decir, emular el extend
método de Python .
Quiero lograr lo siguiente:
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]
Sé que hay un a.concat(b)
método, pero crea una nueva matriz en lugar de simplemente extender la primera. Me gustaría un algoritmo que funcione de manera eficiente cuando a
es significativamente mayor que b
(es decir, uno que no se copia a
).
Nota: ¿ Esto no es un duplicado de Cómo agregar algo a una matriz? - el objetivo aquí es agregar todo el contenido de una matriz a la otra, y hacerlo "en su lugar", es decir, sin copiar todos los elementos de la matriz extendida.
javascript
arrays
concatenation
DzinX
fuente
fuente
a.push(...b)
. Es similar en concepto a la respuesta principal, pero actualizado para ES6.Respuestas:
El
.push
método puede tomar múltiples argumentos. Puede usar el operador de propagación para pasar todos los elementos de la segunda matriz como argumentos para.push
:Si su navegador no es compatible con ECMAScript 6, puede usar
.apply
en su lugar:O tal vez, si crees que está más claro:
Tenga en cuenta que todas estas soluciones fallarán con un error de desbordamiento de la pila si la matriz
b
es demasiado larga (el problema comienza en aproximadamente 100,000 elementos, dependiendo del navegador).Si no puede garantizar que
b
sea lo suficientemente breve, debe utilizar una técnica estándar basada en bucles descrita en la otra respuesta.fuente
push
método de matriz puede tomar cualquier número de argumentos, que luego se envían a la parte posterior de la matriz. Entonces,a.push('x', 'y', 'z')
es una llamada válida que se extenderáa
en 3 elementos.apply
es un método de cualquier función que toma una matriz y usa sus elementos como si todos se hubieran dado explícitamente como elementos posicionales a la función. Pora.push.apply(a, ['x', 'y', 'z'])
lo tanto , también ampliaría la matriz en 3 elementos. Además,apply
toma un contexto como primer argumento (lo pasamosa
nuevamente allí para adjuntarloa
).[].push.apply(a, b)
.Actualización 2018 : Una mejor respuesta es una más reciente mío :
a.push(...b)
. No vuelvas a votar este, ya que en realidad nunca respondió la pregunta, pero fue un truco de 2015 sobre el primer hit en Google :)Para aquellos que simplemente buscaron "JavaScript array extender" y llegaron aquí, pueden usarlo muy bien
Array.concat
.Concat devolverá una copia de la nueva matriz, ya que el iniciador de subprocesos no quería. Pero puede que no te importe (ciertamente para la mayoría de los usos, esto estará bien).
También hay un buen azúcar ECMAScript 6 para esto en forma del operador de propagación:
(También copia).
fuente
arr.push(...arr2)
es más nuevo y mejor y una respuesta técnicamente correcta (tm) a esta pregunta en particular.Debe usar una técnica basada en bucles. Otras respuestas en esta página que se basan en el uso
.apply
pueden fallar para matrices grandes.Una implementación bastante concisa basada en bucles es:
Luego puede hacer lo siguiente:
La respuesta de DzinX (usando push.apply) y otros
.apply
métodos basados fallan cuando la matriz que estamos agregando es grande (las pruebas muestran que para mí grande es> 150,000 entradas aproximadamente en Chrome y> 500,000 entradas en Firefox). Puede ver este error en este jsperf .Se produce un error porque se excede el tamaño de la pila de llamadas cuando se llama a 'Function.prototype.apply' con una matriz grande como segundo argumento. (MDN tiene una nota sobre los peligros de exceder el tamaño de la pila de llamadas usando Function.prototype.apply ; consulte la sección titulada "aplicar y funciones incorporadas").
Para una comparación de velocidad con otras respuestas en esta página, consulte este jsperf (gracias a EaterOfCode). La implementación basada en bucles es similar en velocidad al uso
Array.push.apply
, pero tiende a ser un poco más lenta queArray.slice.apply
.Curiosamente, si la matriz que está agregando es escasa, el
forEach
método basado arriba puede aprovechar la escasez y superar a los.apply
métodos basados; echa un vistazo a este jsperf si quieres probar esto por sí mismo.Por cierto, no se sienta tentado (¡como lo estaba yo!) De acortar aún más la implementación de forEach para:
¡porque esto produce resultados basura! ¿Por qué? Porque
Array.prototype.forEach
proporciona tres argumentos para la función que llama: estos son: (element_value, element_index, source_array). ¡Todos estos serán empujados a su primera matriz para cada iteración deforEach
si usa "forEach (this.push, this)"!fuente
.push.apply
en realidad es mucho más rápido que.forEach
en v8, el más rápido sigue siendo un bucle en línea..forEach
es más rápido que.push.apply
en Chrome / Chromium (en todas las versiones desde v25). No he podido probar v8 de forma aislada, pero si lo has hecho, vincula tus resultados. Ver jsperf: jsperf.com/array-extending-push-vs-concat/5undefined
,.forEach
los omitirá, haciéndolo más rápido..splice
es en realidad el más rápido? jsperf.com/array-extending-push-vs-concat/18Siento que lo más elegante en estos días es:
El artículo de MDN sobre el operador de propagación menciona esta agradable forma azucarada en ES2015 (ES6):
Tenga en cuenta que
arr2
no puede ser enorme (manténgalo en menos de 100 000 artículos), porque la pila de llamadas se desborda, según la respuesta de jcdude.fuente
arr1.push(arr2)
. Esto puede ser un problema, por lo quearr1 = []; arr2=['a', 'b', 'd']; arr1.push(arr2)
el resultado es una matriz de matrices enarr1 == [['a','b','d']]
lugar de dos matrices combinadas. Es un error fácil de cometer. Prefiero su segunda respuesta a continuación por este motivo. stackoverflow.com/a/31521404/4808079.concat
es que el segundo argumento no debe ser una matriz. Esto se puede lograr combinando el operador de propagación conconcat
, por ejemploarr1.push(...[].concat(arrayOrSingleItem))
Primero algunas palabras sobre
apply()
JavaScript para ayudar a entender por qué lo usamos:Push espera una lista de elementos para agregar a la matriz. El
apply()
método, sin embargo, lleva a los argumentos esperados para la llamada de función como una matriz. Esto nos permite fácilmentepush
los elementos de una matriz en otra matriz con elpush()
método incorporado .Imagina que tienes estas matrices:
y simplemente haz esto:
El resultado será:
Lo mismo se puede hacer en ES6 utilizando el operador de propagación ("
...
") de esta manera:Más corto y mejor, pero no totalmente compatible en todos los navegadores en este momento.
Además, si desea mover todo, desde la matriz
b
aa
, vaciarb
en el proceso, puede hacer esto:y el resultado será el siguiente:
fuente
while (b.length) { a.push(b.shift()); }
bien?Si desea usar jQuery, hay $ .merge ()
Ejemplo:
Resultado: a =
[1, 2, 3, 4, 5]
fuente
jQuery.merge()
?Me gusta el
a.push.apply(a, b)
método descrito anteriormente, y si lo desea, siempre puede crear una función de biblioteca como esta:y úsalo así
fuente
Es posible hacerlo usando
splice()
:Pero a pesar de ser más feo, no es más rápido que
push.apply
, al menos no en Firefox 3.0.fuente
Esta solución funciona para mí (usando el operador de propagación de ECMAScript 6):
fuente
Puede crear un polyfill para extender como tengo a continuación. Se agregará a la matriz; en el lugar y regresar, para que pueda encadenar otros métodos.
fuente
Combinando las respuestas ...
fuente
Otra solución para fusionar más de dos matrices.
Luego llame e imprima como:
La salida será:
Array [1, 2, 3, 4, 5, 6, 7]
fuente
La respuesta es super simple.
Concat actúa de manera muy similar a la concatenación de cadenas de JavaScript. Devolverá una combinación del parámetro que pones en la función concat al final de la matriz en la que llamas a la función. El quid es que tienes que asignar el valor devuelto a una variable o se pierde. Así por ejemplo
fuente
Array.prototype.concat()
MDN, esto devolverá una nueva matriz , no se agregará a la matriz existente como OP estaba pidiendo claramente.Use en
Array.extend
lugar deArray.push
para> 150,000 registros.fuente
Súper simple, no cuenta con operadores de propagación ni aplica, si eso es un problema.
Después de ejecutar algunas pruebas de rendimiento en esto, es terriblemente lento, pero responde a la pregunta con respecto a no crear una nueva matriz. Concat es significativamente más rápido, incluso jQuery lo
$.merge()
grita.https://jsperf.com/merge-arrays19b/1
fuente
.forEach
lugar de.map
si no está usando el valor de retorno. Transmite mejor la intención de su código..map
pero también podrías hacerlob.forEach(function(x) { a.push(x)} )
. De hecho, agregué eso a la prueba jsperf y es mucho más rápido que el mapa. Aún súper lento..map
aquí se ve muy raro. Sería como llamarb.filter(x => a.push(x))
. Funciona, pero confunde al lector al implicar que algo está sucediendo cuando no es así..map()
hace y ese es el problema. Este conocimiento me haría pensar que necesita la matriz resultante; de lo contrario, sería bueno utilizarla.forEach()
para que el lector tenga cuidado con los efectos secundarios de la función de devolución de llamada. Hablando estrictamente, su solución crea una matriz adicional de números naturales (resultados depush
), mientras que la pregunta dice: "sin crear una nueva matriz".