¿Cuál es la forma más eficiente de insertar una matriz dentro de otra matriz?
a1 = [1,2,3,4,5];
a2 = [21,22];
newArray - a1.insertAt(2,a2) -> [1,2, 21,22, 3,4,5];
Iterar a2 usando empalme se ve un poco horrible desde el punto de vista del rendimiento si la matriz a2 es grande.
Gracias.
Respuestas:
Puedes usar
splice
combinado con algunosapply
trucos:a1 = [1,2,3,4,5]; a2 = [21,22]; a1.splice.apply(a1, [2, 0].concat(a2)); console.log(a1); // [1, 2, 21, 22, 3, 4, 5];
En ES2015 +, podría usar el operador de propagación en su lugar para hacer esto un poco más agradable
a1.splice(2, 0, ...a2);
fuente
apply
producirá una excepción de desbordamiento de pila . jsfiddle.net/DcHCY También ocurre en jsPerf Creo en FF e IE el umbral es de alrededor de 500ktarget.slice(0, insertIndex).concat(insertArr, target.slice(insertIndex));
jsperf.com/inserting-an-array-within-an-arrayAhora puede hacer esto si usa ES2015 o posterior:
var a1 = [1,2,3,4,5]; var a2 = [21,22]; a1.splice(2, 0, ...a2); console.log(a1) // => [1,2,21,22,3,4,5]
Consulte esto para obtener documentación sobre el operador spread (...) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
fuente
Me equivoqué al principio. Debería haber usado en su
concat()
lugar.var a1 = [1,2,3,4,5], a2 = [21,22], startIndex = 0, insertionIndex = 2, result; result = a1.slice(startIndex, insertionIndex).concat(a2).concat(a1.slice(insertionIndex));
Ejemplo: http://jsfiddle.net/f3cae/1/
Esta expresión usa
slice(0, 2)
[docs] para devolver los dos primeros elementos dea1
(donde0
es el índice inicial y2
es el elemento deleteCount, aunquea1
no se modifica).Resultado intermedio :
[1,2]
Luego usa
concat(a2)
[docs] para agregara2
al final del[1,2]
.Resultado intermedio :
[1,2,21,22]
.A continuación,
a1.slice(2)
se llama dentro de un final.concat()
al final de esta expresión, que equivale a[1,2,21,22].concat(a1.slice(2))
.Una llamada a
slice(2)
, que tiene un argumento entero positivo, devolverá todos los elementos después del segundo elemento, contando por números naturales (como en, hay cinco elementos, por[3,4,5]
lo que se devolverá desdea1
). Otra forma de decir esto es que el argumento de índice entero singular indicaa1.slice()
en qué posición de la matriz comenzar a devolver elementos (el índice 2 es el tercer elemento).Resultado intermedio :
[1,2,21,22].concat([3,4,5])
Finalmente, el segundo se
.concat()
suma[3,4,5]
al final de[1,2,21,22]
.Resultado :
[1,2,21,22,3,4,5]
Puede ser tentador modificarlo
Array.prototype
, pero uno puede simplemente extender el objeto Array usando herencia prototípica e inyectar dicho nuevo objeto en sus proyectos.Sin embargo, para aquellos que viven al límite ...
Ejemplo: http://jsfiddle.net/f3cae/2/
Array.prototype.injectArray = function( idx, arr ) { return this.slice( 0, idx ).concat( arr ).concat( this.slice( idx ) ); }; var a1 = [1,2,3,4,5]; var a2 = [21,22]; var result = a1.injectArray( 2, a2 );
fuente
El operador de extensión permite expandir una expresión en lugares donde se esperan múltiples argumentos (para llamadas a funciones) o múltiples elementos (para matrices literales).
a2 = [21,22]; a1 = [1,2,...a2,3,4,5];//...a2 is use of spread operator console.log(a1);
fuente
Aquí hay algunas respuestas verdaderamente creativas a esta pregunta. Aquí hay una solución simple para aquellos que recién comienzan con matrices. Se puede hacer que funcione hasta los navegadores compatibles con ECMAScript 3, si lo desea.
Sepa algo sobre empalmes antes de comenzar.
Red de desarrolladores de Mozilla: Array.prototype.splice ()
Primero, comprenda dos formas importantes de
.splice()
.let a1 = [1,2,3,4], a2 = [1,2];
Método 1) Elimine los elementos x (deleteCount), comenzando desde un índice deseado.
let startIndex = 0, deleteCount = 2; a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]
Método 2) Eliminar elementos después de un índice de inicio deseado hasta el final de la matriz.
a1.splice(2); // returns [3,4], a1 would be [1,2]
Al usar
.splice()
, un objetivo podría ser dividira1
en matrices de cabeza y cola mediante uno de los dos formularios anteriores.Usando el método n. ° 1, el valor de retorno se convertiría en la cabeza y
a1
la cola.let head = a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]
Ahora, de un solo golpe, concatenar la cabeza, el cuerpo (
a2
) y la colaPor lo tanto, esta solución se parece más al mundo real que cualquier otra presentada hasta ahora. ¿No es esto lo que harías con Legos? ;-) Aquí hay una función, hecha usando el método # 2.
/** *@param target Array The array to be split up into a head and tail. *@param body Array The array to be inserted between the head and tail. *@param startIndex Integer Where to split the target array. */ function insertArray(target, body, startIndex) { let tail = target.splice(startIndex); // target is now [1,2] and the head return [].concat(target, body, tail); } let newArray = insertArray([1, 2, 3, 4], ["a", "b"], 2); // [1, 2, "a", "b", 3, 4]
Corta:
/** *@param target Array The array to be split up into a head and tail. *@param body Array The array to be inserted between the head and tail. *@param startIndex Integer Where to split the target array. */ function insertArray(target, body, startIndex) { return [].concat(target, body, target.splice(startIndex)); }
Más seguro:
/** *@param target Array The array to be split up into a head and tail. *@param body Array The array to be inserted between the head and tail. *@param startIndex Integer Where to split the target array. *@throws Error The value for startIndex must fall between the first and last index, exclusive. */ function insertArray(target, body, startIndex) { const ARRAY_START = 0, ARRAY_END = target.length - 1, ARRAY_NEG_END = -1, START_INDEX_MAGNITUDE = Math.abs(startIndex); if (startIndex === ARRAY_START) { throw new Error("The value for startIndex cannot be zero (0)."); } if (startIndex === ARRAY_END || startIndex === ARRAY_NEG_END) { throw new Error("The startIndex cannot be equal to the last index in target, or -1."); } if (START_INDEX_MAGNITUDE >= ARRAY_END) { throw new Error("The absolute value of startIndex must be less than the last index."); } return [].concat(target, body, target.splice(startIndex)); }
Las ventajas de esta solución incluyen:
1) Una premisa simple domina la solución: llene una matriz vacía.
2) La nomenclatura de la cabeza, el cuerpo y la cola se siente natural.
3) No hay doble llamada a
.slice()
. Sin rebanar en absoluto.4) No
.apply()
. Altamente innecesario.5) Se evita el encadenamiento de métodos.
6) Funciona en ECMAScript 3 y 5 simplemente usando en
var
lugar delet
oconst
.** 7) Asegura que habrá una cabeza y una cola para golpear el cuerpo, a diferencia de muchas otras soluciones presentadas. Si está agregando una matriz antes o después de los límites, al menos debería usar
.concat()
!!!!Nota: El uso del operador de propagación
...
hace que todo esto sea mucho más fácil de lograr.fuente
Quería encontrar una manera de hacer esto
splice()
sin iterar: http://jsfiddle.net/jfriend00/W9n27/ .a1 = [1,2,3,4,5]; a2 = [21,22]; a2.unshift(2, 0); // put first two params to splice onto front of array a1.splice.apply(a1, a2); // pass array as arguments parameter to splice console.log(a1); // [1, 2, 21, 22, 3, 4, 5];
En forma de función de propósito general:
function arrayInsertAt(destArray, pos, arrayToInsert) { var args = []; args.push(pos); // where to insert args.push(0); // nothing to remove args = args.concat(arrayToInsert); // add on array to insert destArray.splice.apply(destArray, args); // splice it in }
fuente
a2
matriz, lo que probablemente sea bastante indeseable. Además, no es necesario que vaya aArray.prototype
cuando tenga la función de corte allí mismo ena1
oa2
.apply()
método.Array.prototype.splice
vsa1.splice
:).concat
devuelve una nueva matriz, no modifica la existente comosplice
. Debería serargs = args.concat(arrayToInsert);
var a1 = [1,2,3,4,5]; var a2 = [21,22]; function injectAt(d, a1, a2) { for(var i=a1.length-1; i>=d; i--) { a1[i + a2.length] = a1[i]; } for(var i=0; i<a2.length; i++) { a1[i+d] = a2[i]; } } injectAt(2, a1, a2); alert(a1);
fuente
Aquí está mi versión sin trucos especiales:
function insert_array(original_array, new_values, insert_index) { for (var i=0; i<new_values.length; i++) { original_array.splice((insert_index + i), 0, new_values[i]); } return original_array; }
fuente
.apply()
.Si desea insertar otra matriz en una matriz sin crear una nueva, la forma más fácil es usar
push
ounshift
conapply
P.ej:
a1 = [1,2,3,4,5]; a2 = [21,22]; // Insert a1 at beginning of a2 a2.unshift.apply(a2,a1); // Insert a1 at end of a2 a2.push.apply(a2,a1);
Esto funciona porque ambos
push
yunshift
toman un número variable de argumentos. ¡Una ventaja adicional es que puede elegir fácilmente desde qué extremo adjuntar la matriz!fuente
a1.concat(a2)
oa2.concat(a1)
he ideado algo más fácil de lo que sugieres. Sin embargo, el problema es insertar una matriz entre los límites de la matriz, no agregar exclusivamente una matriz al principio o al final. ;-)Como se mencionó en otro hilo, las respuestas anteriores no funcionarán en matrices muy grandes (elementos de 200K). Vea aquí una respuesta alternativa que involucra empalme y empuje manual: https://stackoverflow.com/a/41465578/1038326
Array.prototype.spliceArray = function(index, insertedArray) { var postArray = this.splice(index); inPlacePush(this, insertedArray); inPlacePush(this, postArray); function inPlacePush(targetArray, pushedArray) { // Not using forEach for browser compatability var pushedArrayLength = pushedArray.length; for (var index = 0; index < pushedArrayLength; index++) { targetArray.push(pushedArray[index]); } } }
fuente