Estoy buscando un método de inserción de matriz de JavaScript, en el estilo de:
arr.insert(index, item)
Preferiblemente en jQuery, pero cualquier implementación de JavaScript funcionará en este punto.
Estoy buscando un método de inserción de matriz de JavaScript, en el estilo de:
arr.insert(index, item)
Preferiblemente en jQuery, pero cualquier implementación de JavaScript funcionará en este punto.
Respuestas:
Lo que desea es la splice
función en el objeto de matriz nativa.
arr.splice(index, 0, item);
se insertará item
en arr
el índice especificado (eliminando 0
elementos primero, es decir, es solo una inserción).
En este ejemplo crearemos una matriz y le agregaremos un elemento en el índice 2:
var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";
console.log(arr.join());
arr.splice(2, 0, "Lene");
console.log(arr.join());
arr.splice(2,3)
eliminará 3 elementos comenzando en el índice 2. Sin pasar el 3er .... Enésimo parámetro no se inserta nada. Entonces el nombre insert()
tampoco le hace justicia.
Puede implementar el Array.insert
método haciendo esto:
Array.prototype.insert = function ( index, item ) {
this.splice( index, 0, item );
};
Entonces puedes usarlo como:
var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');
// => arr == [ 'A', 'B', 'C', 'D', 'E' ]
Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }
Además del empalme, puede usar este enfoque que no mutará la matriz original, pero creará una nueva matriz con el elemento agregado. Por lo general, debe evitar la mutación siempre que sea posible. Estoy usando el operador de propagación ES6 aquí.
const items = [1, 2, 3, 4, 5]
const insert = (arr, index, newItem) => [
// part of the array before the specified index
...arr.slice(0, index),
// inserted item
newItem,
// part of the array after the specified index
...arr.slice(index)
]
const result = insert(items, 1, 10)
console.log(result)
// [1, 10, 2, 3, 4, 5]
Esto se puede usar para agregar más de un elemento ajustando un poco la función para usar el operador de descanso para los nuevos elementos, y difundir eso también en el resultado devuelto
const items = [1, 2, 3, 4, 5]
const insert = (arr, index, ...newItems) => [
// part of the array before the specified index
...arr.slice(0, index),
// inserted items
...newItems,
// part of the array after the specified index
...arr.slice(index)
]
const result = insert(items, 1, 10, 20)
console.log(result)
// [1, 10, 20, 2, 3, 4, 5]
insert
Métodos de matriz personalizados/* Syntax:
array.insert(index, value1, value2, ..., valueN) */
Array.prototype.insert = function(index) {
this.splice.apply(this, [index, 0].concat(
Array.prototype.slice.call(arguments, 1)));
return this;
};
Puede insertar múltiples elementos (como lo splice
hace el nativo ) y admite el encadenamiento:
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]
/* Syntax:
array.insert(index, value1, value2, ..., valueN) */
Array.prototype.insert = function(index) {
index = Math.min(index, this.length);
arguments.length > 1
&& this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
&& this.insert.apply(this, arguments);
return this;
};
Puede fusionar matrices de los argumentos con la matriz dada y también admite el encadenamiento:
["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"
["b", "X", "Y", "Z", "c"]
. ¿Por qué no está "d"
incluido? Me parece que si pones 6 como el segundo parámetro de slice()
y hay 6 elementos en la matriz a partir del índice especificado, entonces deberías obtener los 6 elementos en el valor de retorno. (El documento dice howMany
para ese parámetro). Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3);
=>[ ]
slice
método y no splice
, a lo que te refieres en el comentario. El segundo parámetro de slice
(named end
) es un índice basado en cero en el que finalizar la extracción. slice
extractos hasta pero no incluidosend
. Por lo tanto, después de insert
que tiene ["a", "b", "X", "Y", "Z", "c", "d"]
, de donde slice
extrae elementos con índices de 1
hasta 6
, es decir, de "b"
hasta "d"
pero no incluidos "d"
. ¿Tiene sentido?
Si desea insertar varios elementos en una matriz a la vez, consulte esta respuesta de desbordamiento de pila: una mejor manera de empalmar una matriz en una matriz en javascript
También aquí hay algunas funciones para ilustrar ambos ejemplos:
function insertAt(array, index) {
var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
return insertArrayAt(array, index, arrayToInsert);
}
function insertArrayAt(array, index, arrayToInsert) {
Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
return array;
}
Finalmente, aquí hay un jsFiddle para que pueda verlo por usted mismo: http://jsfiddle.net/luisperezphd/Wc8aS/
Y así es como usas las funciones:
// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");
// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);
Para fines de programación funcional y encadenamiento adecuados, Array.prototype.insert()
es esencial una invención . En realidad, el empalme podría haber sido perfecto si hubiera devuelto la matriz mutada en lugar de una matriz vacía totalmente sin sentido. Así que aquí va
Array.prototype.insert = function(i,...rest){
this.splice(i,0,...rest)
return this
}
var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");
Bien, lo anterior con el Array.prototype.splice()
que muta la matriz original y algunos podrían quejarse como "no deberías modificar lo que no te pertenece" y eso podría resultar correcto también. Entonces, para el bienestar público, me gustaría dar otro Array.prototype.insert()
que no mute la matriz original. Aquí va;
Array.prototype.insert = function(i,...rest){
return this.slice(0,i).concat(rest,this.slice(i));
}
var a = [3,4,8,9],
b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));
splice
muta la matriz original, no creo que la "programación funcional adecuada" pertenezca a ninguna parte cercana splice
.
Recomiendo usar JavaScript puro en este caso, tampoco hay un método de inserción en JavaScript, pero tenemos un método que es un método Array incorporado que hace el trabajo por usted, se llama empalme ...
Veamos qué es splice () ...
El método splice () cambia el contenido de una matriz al eliminar elementos existentes y / o agregar nuevos elementos.
OK, imagina que tenemos esta matriz a continuación:
const arr = [1, 2, 3, 4, 5];
Podemos eliminar 3
así:
arr.splice(arr.indexOf(3), 1);
Devolverá 3, pero si verificamos el arr ahora, tenemos:
[1, 2, 4, 5]
Hasta ahora, todo bien, pero ¿cómo podemos agregar un nuevo elemento a la matriz usando empalme? Pongamos de nuevo 3 en el arr ...
arr.splice(2, 0, 3);
Veamos que hemos hecho ...
Usamos el empalme nuevamente, pero esta vez para el segundo argumento, pasamos 0 , significa que no queremos eliminar ningún elemento, pero al mismo tiempo, agregamos un tercer argumento que es 3 que se agregará en el segundo índice ...
Debe tener en cuenta que podemos eliminar y agregar al mismo tiempo, por ejemplo, ahora podemos hacer:
arr.splice(2, 2, 3);
Lo cual eliminará 2 elementos en el índice 2, luego agregará 3 en el índice 2 y el resultado será:
[1, 2, 3, 5];
Esto muestra cómo funciona cada elemento en el empalme:
array.splice (inicio, deleteCount, item1, item2, item3 ...)
Agregar elemento individual en un índice específico
//Append at specific position(here at index 1)
arrName.splice(1, 0,'newName1');
//1: index number, 0: number of element to remove, newName1: new element
//Append at specific position (here at index 3)
arrName[3] = 'newName1';
Agregar elementos múltiples en un índice específico
//Append from index number 1
arrName.splice(1, 0,'newElemenet1', 'newElemenet2', 'newElemenet3');
//1: index number from where append start,
//0: number of element to remove,
//newElemenet1,2,3: new elements
arrName[3] = 'newName1';
se agregará si la matriz tiene solo 3 elementos. Si hay un elemento en el índice 3, este será reemplazado. Si desea agregar al final, es mejor usarloarrName.push('newName1');
Otra posible solución, con el uso de Array#reduce
.
var arr = ["apple", "orange", "raspberry"],
arr2 = [1, 2, 4];
function insert(arr, item, index) {
arr = arr.reduce(function(s, a, i) {
i == index ? s.push(item, a) : s.push(a);
return s;
}, []);
console.log(arr);
}
insert(arr, "banana", 1);
insert(arr2, 3, 2);
Aquí hay dos formas:
const array = [ 'My', 'name', 'Hamza' ];
array.splice(2, 0, 'is');
console.log("Method 1 : ", array.join(" "));
O
Array.prototype.insert = function ( index, item ) {
this.splice( index, 0, item );
};
const array = [ 'My', 'name', 'Hamza' ];
array.insert(2, 'is');
console.log("Method 2 : ", array.join(" "));
Aunque esto ya ha sido respondido, estoy agregando esta nota para un enfoque alternativo.
Quería colocar un número conocido de elementos en una matriz, en posiciones específicas, ya que provienen de una "matriz asociativa" (es decir, un objeto) que por definición no se garantiza que esté en un orden ordenado. Quería que la matriz resultante fuera una matriz de objetos, pero los objetos estarían en un orden específico en la matriz ya que una matriz garantiza su orden. Entonces hice esto.
Primero el objeto fuente, una cadena JSONB recuperada de PostgreSQL. Quería ordenarlo por la propiedad "orden" en cada objeto secundario.
var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';
var jsonb_obj = JSON.parse(jsonb_str);
Como se conoce el número de nodos en el objeto, primero creo una matriz con la longitud especificada:
var obj_length = Object.keys(jsonb_obj).length;
var sorted_array = new Array(obj_length);
Y luego itere el objeto, colocando los objetos temporales recién creados en las ubicaciones deseadas en la matriz sin que realmente tenga lugar ninguna "clasificación".
for (var key of Object.keys(jsonb_obj)) {
var tobj = {};
tobj[key] = jsonb_obj[key].abbr;
var position = jsonb_obj[key].order - 1;
sorted_array[position] = tobj;
}
console.dir(sorted_array);
Cualquiera que todavía tenga problemas con este y haya probado todas las opciones anteriores y nunca lo haya obtenido. Estoy compartiendo mi solución, esto es para tener en cuenta que no desea indicar explícitamente las propiedades de su objeto frente a la matriz.
function isIdentical(left, right){
return JSON.stringify(left) === JSON.stringify(right);
}
function contains(array, obj){
let count = 0;
array.map((cur) => {
if(this.isIdentical(cur, obj)) count++;
});
return count > 0;
}
Esta es una combinación de iterar la matriz de referencia y compararla con el objeto que desea verificar, convertir ambos en una cadena y luego iterar si coincide. Entonces puedes contar. Esto se puede mejorar, pero aquí es donde me instalé. Espero que esto ayude.
Aprovechando el método de reducción de la siguiente manera:
function insert(arr, val, index) {
return index >= arr.length
? arr.concat(val)
: arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);
}
Entonces, de esta manera podemos devolver una nueva matriz (será una forma funcional genial, mucho mejor que usar push o splice) con el elemento insertado en el índice, y si el índice es mayor que la longitud de la matriz, se insertará al final.
Array#splice()
es el camino a seguir, a menos que realmente desee evitar mutar la matriz. Dado 2 matrices arr1
y arr2
, he aquí cómo usted insertar el contenido de arr2
dentro arr1
después de que el primer elemento:
const arr1 = ['a', 'd', 'e'];
const arr2 = ['b', 'c'];
arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']
console.log(arr1)
Si le preocupa la mutación de la matriz (por ejemplo, si usa Immutable.js), puede usar slice()
, no confundir con splice()
a 'p'
.
const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];
¡Intenté esto y está funcionando bien!
var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);
El índice es la posición donde desea insertar o eliminar el elemento. 0 es decir, el segundo parámetro define la cantidad de elementos del elemento que se eliminará del índice que son las nuevas entradas que desea hacer en la matriz. Puede ser uno o más de uno.
initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");
Aquí hay una función de trabajo que uso en una de mis aplicaciones.
Esto comprueba si el elemento sale
let ifExist = (item, strings = [ '' ], position = 0) => {
// output into an array with empty string. Important just in case their is no item.
let output = [ '' ];
// check to see if the item that will be positioned exist.
if (item) {
// output should equal to array of strings.
output = strings;
// use splice in order to break the array.
// use positition param to state where to put the item
// and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position.
output.splice(position, 0, item);
}
//empty string is so we do not concatenate with comma or anything else.
return output.join("");
};
Y luego lo llamo a continuación.
ifExist("friends", [ ' ( ', ' )' ], 1)} // output: ( friends )
ifExist("friends", [ ' - '], 1)} // output: - friends
ifExist("friends", [ ':'], 0)} // output: friends:
Un poco más antiguo, pero tengo que estar de acuerdo con Redu anterior porque el empalme definitivamente tiene una interfaz un poco confusa. Y la respuesta dada por cdbajorin de que "solo devuelve una matriz vacía cuando el segundo parámetro es 0. Si es mayor que 0, devuelve los elementos eliminados de la matriz" es, si bien exacto, prueba el punto. La intención de la función es empalmar o, como dijo anteriormente Jakob Keller, "unirse o conectarse, también cambiar. Tiene una matriz establecida que ahora está cambiando que implicaría agregar o eliminar elementos ..." Dado eso, el El valor de retorno de los elementos, si los hay, que se eliminaron es, en el mejor de los casos, incómodo. Y estoy 100% de acuerdo en que este método podría haber sido más adecuado para encadenar si hubiera devuelto lo que parece natural, una nueva matriz con los elementos empalmados agregados. Entonces podría hacer cosas como ["19", "17"]. Empalmar (1,0, "18"). Unirse ("...") o lo que quiera con la matriz devuelta. El hecho de que devuelva lo que se eliminó es simplemente una tontería en mi humilde opinión. Si la intención del método era "cortar un conjunto de elementos" y esa era su única intención, tal vez. Sin embargo, parece que si no sé lo que estoy cortando, probablemente tenga pocas razones para eliminar esos elementos, ¿no? Sería mejor si se comportara como concat, map, reduce, slice, etc., donde se crea una nueva matriz a partir de la matriz existente en lugar de mutar la matriz existente. Esos son todos encadenados, y ES un problema importante. Es bastante común en la manipulación de la matriz de cadena. Parece que el idioma necesita ir en una u otra dirección y tratar de mantenerlo lo más posible. Javascript es funcional y menos declarativo, solo parece una extraña desviación de la norma.
Hoy (2020.04.24) realizo pruebas para soluciones elegidas para matrices grandes y pequeñas. Los probé en MacOs High Sierra 10.13.6 en Chrome 81.0, Safari 13.1, Firefox 75.0.
Para todos los navegadores
slice
y reduce
(D, E, F) suelen ser 10x-100x más rápidas que las soluciones in situ.splice
(AI, BI, CI) fueron más rápidas (a veces ~ 100x, pero depende del tamaño de la matriz)Las pruebas se dividieron en dos grupos: soluciones en el lugar (AI, BI, CI) y soluciones no en el lugar (D, E, F) y se realizaron durante dos casos
El código probado se presenta en el siguiente fragmento
Los resultados de ejemplo para una matriz pequeña en Chrome están a continuación