into - splice javascript
Cómo extender una matriz de JavaScript existente con otra matriz, sin crear una nueva matriz (14)
Combinando las respuestas ...
Array.prototype.extend = function(array) {
if (array.length < 150000) {
this.push.apply(this, array)
} else {
for (var i = 0, len = array.length; i < len; ++i) {
this.push(array[i]);
};
}
}
No parece haber una manera de extender una matriz de JavaScript existente con otra matriz, es decir, emular el método de extend
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)
, pero crea una nueva matriz en lugar de simplemente extender la primera. Me gustaría un algoritmo que funcione eficientemente cuando a
es significativamente mayor que b
(es decir, uno que no copia a
).
Nota: Este 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.
Debe utilizar una técnica basada en bucle. Otras respuestas en esta página que se basan en el uso de .apply
pueden fallar para arreglos grandes.
Una implementación basada en bucles bastante concisos es:
Array.prototype.extend = function (other_array) {
/* You should include a test to check whether other_array really is an array */
other_array.forEach(function(v) {this.push(v)}, this);
}
A continuación, puede hacer lo siguiente:
var a = [1,2,3];
var b = [5,4,3];
a.extend(b);
La respuesta de DzinX (usando push.apply) y otros métodos basados en .apply
fallan cuando la matriz que estamos agregando es grande (las pruebas muestran que para mí es grande> 150,000 entradas aproximadamente en Chrome y> 500,000 entradas en Firefox). Puedes ver este error ocurriendo 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 .apply - vea la sección titulada "funciones incorporadas y incorporadas".)
Para una comparación de velocidad con otras respuestas en esta página, echa un vistazo a este jsperf (gracias a EaterOfCode). La implementación basada en bucles es similar en velocidad al uso de Array.push.apply
, pero tiende a ser un poco más lenta que Array.slice.apply
.
Curiosamente, si la matriz que está agregando es escasa, el método basado en forEach
anterior puede aprovechar la dispersión y superar a los métodos basados en .apply
; Echa un vistazo a este jsperf si quieres probar esto por ti mismo.
Por cierto, no se sienta tentado (¡como lo estaba yo!) A acortar aún más la implementación de forEach para:
Array.prototype.extend = function (array) {
array.forEach(this.push, this);
}
¡Porque esto produce resultados basura! ¿Por qué? Debido a que 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 en su primer conjunto para cada iteración de forEach
si usa "forEach (this.push, this)"!
El método .push
puede tomar múltiples argumentos, por lo que al usar .apply
para pasar todos los elementos de la segunda matriz como argumentos a .push
, puede obtener el resultado que desea:
>>> a.push.apply(a, b)
O tal vez, si piensas que es más claro:
>>> Array.prototype.push.apply(a,b)
Si su navegador es compatible con ECMAScript 6, puede usar el operador de propagación , que es más compacto y elegante:
>>> a.push(...b)
Tenga en cuenta que todas estas soluciones fallarán con un error de desbordamiento de pila si la matriz b
es demasiado larga (los problemas comienzan en aproximadamente 100,000 elementos, según el navegador). Si no puede garantizar que b
sea lo suficientemente corto, debe usar una técnica estándar basada en bucles descrita en la otra respuesta.
Es posible hacerlo usando splice()
:
b.unshift(b.length)
b.unshift(a.length)
Array.prototype.splice.apply(a,b)
b.shift() // Restore b
b.shift() //
Pero a pesar de ser más feo, no es más rápido que push.apply
, al menos no en Firefox 3.0.
Esta solución funciona para mí (utilizando el operador de difusión de ECMAScript 6):
let array = [''my'', ''solution'', ''works''];
let newArray = [];
let newArray2 = [];
newArray.push(...array); // Adding to same array
newArray2.push([...array]); // Adding as child/leaf/sub-array
console.log(newArray);
console.log(newArray2);
La respuesta es super simple.
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
(The following code will combine the two arrays.)
a = a.concat(b);
>>> a
[1, 2, 3, 4, 5]
Concat actúa de manera muy similar a la concatenación de cadenas de JavaScript. Devolverá una combinación del parámetro que puso en la función concat al final de la matriz a la que llama la función. El problema es que debe asignar el valor devuelto a una variable o se perderá. Así por ejemplo
a.concat(b); <--- This does absolutely nothing since it is just returning the combined arrays, but it doesn''t do anything with it.
Me gusta el a.push.apply(a, b)
descrito anteriormente, y si lo desea, siempre puede crear una función de biblioteca como esta:
Array.prototype.append = function(array)
{
this.push.apply(this, array)
}
y usalo asi
a = [1,2]
b = [3,4]
a.append(b)
Otra solución para fusionar más de dos arrays.
var a = [1, 2],
b = [3, 4, 5],
c = [6, 7];
// Merge the contents of multiple arrays together into the first array
var mergeArrays = function() {
var i, len = arguments.length;
if (len > 1) {
for (i = 1; i < len; i++) {
arguments[0].push.apply(arguments[0], arguments[i]);
}
}
};
Luego llame e imprima como:
mergeArrays(a, b, c);
console.log(a)
La salida será: Array [1, 2, 3, 4, 5, 6, 7]
Primero unas palabras sobre apply()
en JavaScript para ayudar a entender por qué lo usamos:
El método
apply()
llama a una función con un valor dado dethis
, y a los argumentos proporcionados como una matriz.
Push espera una lista de elementos para agregar a la matriz. El método apply()
, sin embargo, toma los argumentos esperados para la llamada a la función como una matriz. Esto nos permite push
fácilmente los elementos de una matriz en otra matriz con el método push()
incorporado.
Imagina que tienes estos arreglos:
var a = [1, 2, 3, 4];
var b = [5, 6, 7];
y simplemente haga esto:
Array.prototype.push.apply(a, b);
El resultado será:
a = [1, 2, 3, 4, 5, 6, 7];
Lo mismo se puede hacer en ES6 usando el operador de propagación (" ...
") de la siguiente manera:
a.push(...b); //a = [1, 2, 3, 4, 5, 6, 7];
Más corto y mejor, pero no totalmente compatible con todos los navegadores en este momento.
Además, si desea mover todo de la matriz b
a a
, vaciar b
en el proceso, puede hacer esto:
while(b.length) {
a.push(b.shift());
}
y el resultado será el siguiente:
a = [1, 2, 3, 4, 5, 6, 7];
b = [];
Puede crear un polyfill para extender como tengo a continuación. Se agregará a la matriz; en el lugar y devuélvase, para que pueda encadenar otros métodos.
if (Array.prototype.extend === undefined) {
Array.prototype.extend = function(other) {
this.push.apply(this, arguments.length > 1 ? arguments : other);
return this;
};
}
function print() {
document.body.innerHTML += [].map.call(arguments, function(item) {
return typeof item === ''object'' ? JSON.stringify(item) : item;
}).join('' '') + ''/n'';
}
document.body.innerHTML = '''';
var a = [1, 2, 3];
var b = [4, 5, 6];
print(''Concat'');
print(''(1)'', a.concat(b));
print(''(2)'', a.concat(b));
print(''(3)'', a.concat(4, 5, 6));
print(''/nExtend'');
print(''(1)'', a.extend(b));
print(''(2)'', a.extend(b));
print(''(3)'', a.extend(4, 5, 6));
body {
font-family: monospace;
white-space: pre;
}
Puedo ver muy buenas respuestas, y todo depende del tamaño de su matriz, sus requisitos y su objetivo. Se puede hacer de diferentes maneras.
Sugiero usar un JavaScript para el bucle:
var a = [1, 2];
var b = [3, 4, 5];
for (i = 0; i < b.length; i++) {
a.push(b[i]);
}
console.log(a)
salida de console.log(a)
será
Array [ 1, 2, 3, 4, 5 ]
Entonces puedes hacer tu propia función:
function extendArray(a, b){
for (i = 0; i < b.length; i++) {
a.push(b[i]);
}
return a;
}
console.log(extendArray(a, b));
la salida será
Array [ 1, 2, 3, 4, 5 ]
Si quieres usar jQuery, hay $.merge()
Ejemplo:
a = [1, 2];
b = [3, 4, 5];
$.merge(a,b);
Resultado: a = [1, 2, 3, 4, 5]
Siento que lo más elegante de estos días es:
arr1.push(...arr2);
El artículo de MDN sobre el operador de propagación menciona esta buena forma azucarada en ES2015 (ES6):
Un mejor empuje
Ejemplo: push se usa a menudo para empujar una matriz al final de una matriz existente. En ES5 esto se hace a menudo como:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Append all items from arr2 onto arr1 Array.prototype.push.apply(arr1, arr2);
En ES6 con spread esto se convierte en:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1.push(...arr2);
Tenga en cuenta que arr2
no puede ser enorme (manténgalo por debajo de 100 000 elementos), ya que la pila de llamadas se desborda, según la respuesta de jcdude.
Actualización 2018 : una mejor respuesta es una más nueva mía : a.push(...b)
. No vuelvas a votar este, ya que en realidad nunca respondió a la pregunta, pero fue un truco de 2015 alrededor del primer éxito en Google :)
Para aquellos que simplemente buscaron "extensión de matriz de JavaScript" y llegaron aquí, puede usar Array.concat
.
var a = [1, 2, 3];
a = a.concat([5, 4, 3]);
Concat devolverá una copia de la nueva matriz, ya que el iniciador de subprocesos no quería. Pero puede que no te importe (sin duda para la mayoría de los usos, esto estará bien).
También hay un poco de azúcar ECMAScript 6 agradable para esto en la forma del operador de propagación:
const a = [1, 2, 3];
const b = [...a, 5, 4, 3];
(También copia.)