Eliminar elementos de matriz en JavaScript - eliminar vs empalmar

1334

¿Cuál es la diferencia entre usar el deleteoperador en el elemento de matriz en lugar de usar el Array.splicemétodo ?

Por ejemplo:

myArray = ['a', 'b', 'c', 'd'];

delete myArray[1];
//  or
myArray.splice (1, 1);

¿Por qué incluso tener el método de empalme si puedo eliminar elementos de matriz como puedo con los objetos?

lYriCAlsSH
fuente
3
Para los .splicebucles, eche un vistazo a esta pregunta: Eliminar de la matriz en javascript .
Rob W
66
@andynormancx Sí, pero esta respuesta se publicó justo el día después y obtuvo muchos más votos. Diría que es mejor escribir, eso debe ser todo.
Camilo Martin
@andynormancx: no parece ser un duplicado exacto. La pregunta que vinculó es básicamente preguntar por qué eliminar un elemento de una matriz (lo que lo hace escaso) no reducirá su longitud. Esta pregunta es preguntar por las diferencias entre deletey Array.prototype.splice.
chharvey
@chharvey estuvo de acuerdo, lo que es más importante, ¿cómo puede haber sido publicada esta pregunta hace 9 años? Me hace sentir viejo para volver aquí comentando al respecto
andynormancx

Respuestas:

1693

deleteeliminará la propiedad del objeto, pero no reindexará la matriz ni actualizará su longitud. Esto hace que parezca que no está definido:

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> delete myArray[0]
  true
> myArray[0]
  undefined

Tenga en cuenta que, de hecho, no está establecido en el valor undefined, sino que la propiedad se elimina de la matriz, lo que hace que parezca indefinido. Las herramientas de desarrollo de Chrome aclaran esta distinción al imprimir emptyal iniciar la matriz.

> myArray[0]
  undefined
> myArray
  [empty, "b", "c", "d"]

myArray.splice(start, deleteCount) en realidad elimina el elemento, reindexa la matriz y cambia su longitud.

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]
Andy Hume
fuente
74
En realidad, delete hace retirar el elemento, pero no indexar la matriz o actualizar su longitud (que ya está implícita por el anterior ya que la longitud es siempre el más alto índice + 1).
Felix Kling
3
A JSlint no le gusta la delete myArray[0]sintaxis que dice " Esperaba un operador y en su lugar vio 'eliminar' " .splice Se recomienda usar .
Ojo
21
@Eye: En realidad, JSLint solo se queja de la falta de un punto y coma en la línea anterior. Y realmente no puedes recomendar uno sobre el otro, ya que hacen cosas completamente diferentes ...
Ry-
3
"Eliminar en este caso solo establecerá el elemento como indefinido:" No, eso es completamente incorrecto. Hay una diferencia fundamental entre delete myArray[0]y myArray[0] = undefined. En el primer caso, la propiedad se elimina del objeto de matriz por completo. En el segundo caso, la propiedad permanece con el valor undefined.
TJ Crowder
1
Para su información, las herramientas de desarrollo de Chrome muestran la palabra clave en emptylugar de undefinedmejorar la distinción entre un elemento de matriz realmente eliminado (o no inicializado) frente a un elemento que tiene el valor real de undefined. Tenga en cuenta que cuando digo esto quiero decir que solo se muestra como empty, y no se refiere a un valor real llamado empty(que no existe).
chharvey
340

Método Array.remove ()

John Resig , creador de jQuery creó un Array.removemétodo muy útil que siempre lo uso en mis proyectos.

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

y aquí hay algunos ejemplos de cómo podría usarse:

// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);

El sitio web de John

Mohsen
fuente
44
+1 para Array.remove (). Sin embargo, no es feliz que se pasen argumentos de cadena (a diferencia de la mayoría de los métodos de matriz, por ejemplo [1,2,3].slice('1'); // =[2,3]), por lo que es más seguro cambiarlo avar rest = this.slice(parseInt(to || from) + 1 || this.length);
Richard Inglis
1
@tomwrong, no hay hilos en javascript, y la función se ejecuta this.push.apply(this, rest), luego devuelve el valor que devolvió
billy
59
Esto no responde a la pregunta en absoluto.
Ry-
16
¿Por qué no solo usar splice ()? El nombre de esta función, los nombres de los parámetros y los resultados no son obvios. Mi recomendación es simplemente usar empalme (índice, longitud) - (ver la respuesta de Andy Hume)
auco
3
La función proporcionada anteriormente funciona como se explicó, pero crea efectos secundarios no deseados cuando se itera a través de la matriz con el for(var i in array)ciclo. Lo eliminé y usé empalme en su lugar.
alexykot
104

Debido a que eliminar solo elimina el objeto del elemento en la matriz, la longitud de la matriz no cambiará. Splice elimina el objeto y acorta la matriz.

El siguiente código mostrará "a", "b", "indefinido", "d"

myArray = ['a', 'b', 'c', 'd']; delete myArray[2];

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

Mientras que esto mostrará "a", "b", "d"

myArray = ['a', 'b', 'c', 'd']; myArray.splice(2,1);

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}
andynormancx
fuente
11
gran ejemplo, excepto la ambigüedad en el segundo ejemplo al usar 1,1: el primer 1 se refiere al índice en la matriz para iniciar el empalme, el segundo 1 es el número de elementos que se eliminarán. Entonces, para eliminar 'c' de la matriz original, usemyArray.splice(2,1)
iancoleman el
68

Me topé con esta pregunta al tratar de entender cómo eliminar cada aparición de un elemento de una matriz. Aquí hay una comparación de splicey deletepara eliminar cada uno 'c'de la itemsmatriz.

var items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  items.splice(items.indexOf('c'), 1);
}

console.log(items); // ["a", "b", "d", "a", "b", "d"]

items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  delete items[items.indexOf('c')];
}

console.log(items); // ["a", "b", undefined, "d", "a", "b", undefined, "d"]
Troy Harvey
fuente
10

splice funcionará con índices numéricos.

mientras que deletese puede usar contra otro tipo de índices.

ejemplo:

delete myArray['text1'];
Gopal
fuente
99
Cuando dices 'cualquier otro tipo de índices', ya no estás hablando de matrices, sino de objetos, que es lo que pregunta el OP.
Yi Jiang el
2
@YiJiang: Las matrices son objetos. Indica que son propiedades. No hay diferencia.
Bergi
9

Probablemente también valga la pena mencionar que el empalme solo funciona en matrices. (No se puede confiar en que las propiedades de los objetos sigan un orden coherente).

Para eliminar el par clave-valor de un objeto, eliminar es realmente lo que desea:

delete myObj.propName;     // , or:
delete myObj["propName"];  // Equivalent.
jtrick
fuente
eliminar no reordena las claves de la matriz, por lo que: var arr = [1,2,3,4,5]; eliminar arr [3]; for (var i = 0; i <= arr.length; i ++) console.log (arr [i]); exhibirá resultados inesperados.
Kristian Williams el
Esto es verdad. Entonces, a menos que desee dejar un elemento indefinido en esa ubicación, ¡NO use eliminar en las teclas de una matriz! Originalmente agregué este comentario para incluir una referencia del uso correcto de eliminar.
jtrick
pero ¿por qué eliminar arrojará resultados inesperados?
Alex
9

eliminar Vs splice

cuando eliminas un elemento de una matriz

var arr = [1,2,3,4]; delete arr[2]; //result [1, 2, 3:, 4]
console.log(arr)

cuando empalmes

var arr = [1,2,3,4]; arr.splice(1,1); //result [1, 3, 4]
console.log(arr);

en caso de eliminar, el elemento se elimina pero el índice permanece vacío

mientras que en caso de que el elemento de empalme se elimine y el índice de elementos de descanso se reduzca en consecuencia

Ashish Yadav
fuente
8

Como se indicó muchas veces anteriormente, el uso splice()parece un ajuste perfecto. Documentación en Mozilla:

El splice()método cambia el contenido de una matriz eliminando elementos existentes y / o agregando elementos nuevos.

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];

myFish.splice(2, 0, 'drum'); 
// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]

myFish.splice(2, 1); 
// myFish is ["angel", "clown", "mandarin", "sturgeon"]

Sintaxis

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)

Parámetros

comienzo

Índice en el que comenzar a cambiar la matriz. Si es mayor que la longitud de la matriz, el índice inicial real se establecerá en la longitud de la matriz. Si es negativo, comenzarán tantos elementos desde el final.

deleteCount

Un entero que indica el número de elementos de matriz antiguos que se eliminarán. Si deleteCount es 0, no se eliminan elementos. En este caso, debe especificar al menos un nuevo elemento. Si deleteCount es mayor que la cantidad de elementos que quedan en la matriz desde el inicio, se eliminarán todos los elementos hasta el final de la matriz.

Si se omite deleteCount, deleteCount será igual a (arr.length - start).

item1, item2, ...

Los elementos para agregar a la matriz, comenzando en el índice de inicio. Si no especifica ningún elemento, splice()solo eliminará elementos de la matriz.

Valor de retorno

Una matriz que contiene los elementos eliminados. Si solo se elimina un elemento, se devuelve una matriz de un elemento. Si no se eliminan elementos, se devuelve una matriz vacía.

[...]

serv-inc
fuente
@downvoter: ¿por qué el downvote? ¿te importaría explicarlo o no?
serv-inc
7

delete actúa como una situación del mundo no real, solo elimina el elemento, pero la longitud de la matriz permanece igual:

ejemplo de terminal de nodo:

> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]

Aquí hay una función para eliminar un elemento de una matriz por índice, usando slice () , toma el arr como el primer argumento y el índice del miembro que desea eliminar como el segundo argumento. Como puede ver, en realidad elimina el miembro de la matriz y reducirá la longitud de la matriz en 1

function(arr,arrIndex){
    return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}

Lo que hace la función anterior es llevar todos los miembros al índice, y todos los miembros después del índice, y los concatena juntos, y devuelve el resultado.

Aquí hay un ejemplo usando la función anterior como un módulo de nodo, ver el terminal será útil:

> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4 
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3

tenga en cuenta que esto no funcionará en una matriz con duplicados, porque indexOf ("c") solo obtendrá la primera aparición, y solo empalmará y eliminará la primera "c" que encuentre.

med116
fuente
6

Si desea iterar una matriz grande y eliminar elementos de forma selectiva, sería costoso llamar a splice () para cada eliminación porque splice () tendría que volver a indexar los elementos posteriores cada vez. Debido a que las matrices son asociativas en Javascript, sería más eficiente eliminar los elementos individuales y luego volver a indexar la matriz.

Puedes hacerlo construyendo una nueva matriz. p.ej

function reindexArray( array )
{
       var result = [];
        for( var key in array )
                result.push( array[key] );
        return result;
};

Pero no creo que pueda modificar los valores clave en la matriz original, lo que sería más eficiente: parece que tendrá que crear una nueva matriz.

Tenga en cuenta que no necesita verificar las entradas "indefinidas" ya que en realidad no existen y el bucle for no las devuelve. Es un artefacto de la impresión de matriz que los muestra como indefinidos. No parecen existir en la memoria.

Sería bueno si pudieras usar algo como slice () que sería más rápido, pero no se vuelve a indexar. Alguien sabe de una mejor manera?


En realidad, probablemente pueda hacerlo en el lugar de la siguiente manera, que probablemente sea más eficiente, en términos de rendimiento:

reindexArray : function( array )
{
    var index = 0;                          // The index where the element should be
    for( var key in array )                 // Iterate the array
    {
        if( parseInt( key ) !== index )     // If the element is out of sequence
        {
            array[index] = array[key];      // Move it to the correct, earlier position in the array
            ++index;                        // Update the index
        }
    }

    array.splice( index );  // Remove any remaining elements (These will be duplicates of earlier items)
},
Mike T
fuente
Creo el índice ++; necesita suceder fuera del 'si'. Hacer edición
mishal153
6

puedes usar algo como esto

var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';})); // [1,2,3,4,6]

Zeeshan Saleem
fuente
Esto es más intuitivo que slicesi proviene de un entorno funcional (aunque probablemente menos eficiente).
jethro
3

¿Por qué no solo filtrar? Creo que es la forma más clara de considerar las matrices en js.

myArray = myArray.filter(function(item){
    return item.anProperty != whoShouldBeDeleted
});
Asqan
fuente
¿Qué pasa con una matriz con cientos (si no miles) de registros donde solo 3 de ellos deben eliminarse?
Joel Hernández
buen punto. Utilizo este método para matrices dispersas cuya longitud no es más de 200 o 300 y funciona muy bien. Sin embargo, creo que las bibliotecas como subrayado deberían preferirse si tiene que gestionar matrices tan grandes.
Asqan
1
Sin embargo, parece mucho mejor que deleteni slicea mí.
Juneyoung Oh,
3

La diferencia se puede ver registrando la longitud de cada matriz después de aplicar el deleteoperador y el splice()método. Por ejemplo:

eliminar operador

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];

console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees.length); // 5

El deleteoperador elimina el elemento de la matriz, pero el "marcador de posición" del elemento todavía existe. oakse ha eliminado pero todavía ocupa espacio en la matriz. Debido a esto, la longitud de la matriz sigue siendo 5.

método de empalme ()

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);

console.log(trees); // ["redwood", "bay", "cedar", "maple"]
console.log(trees.length); // 4

El splice()método elimina completamente el valor objetivo y el "marcador de posición" también. oakse ha eliminado, así como el espacio que solía ocupar en la matriz. La longitud de la matriz es ahora 4.

underthecode
fuente
2
function remove_array_value(array, value) {
    var index = array.indexOf(value);
    if (index >= 0) {
        array.splice(index, 1);
        reindex_array(array);
    }
}
function reindex_array(array) {
   var result = [];
    for (var key in array) {
        result.push(array[key]);
    }
    return result;
}

ejemplo:

var example_arr = ['apple', 'banana', 'lemon'];   // length = 3
remove_array_value(example_arr, 'banana');

el plátano se elimina y la longitud de la matriz = 2

Terry Lin
fuente
2

Son cosas diferentes que tienen propósitos diferentes.

splicees específico de la matriz y, cuando se usa para eliminar, elimina las entradas de la matriz y mueve todas las entradas anteriores para llenar el vacío. (También se puede usar para insertar entradas, o ambas al mismo tiempo). spliceCambiará lengthla matriz (suponiendo que no sea una llamada no operativa:) theArray.splice(x, 0).

deleteno es específico de la matriz; Está diseñado para su uso en objetos: elimina una propiedad (par clave / valor) del objeto en el que lo usa. Solo se aplica a las matrices porque las matrices estándar (por ejemplo, no tipificadas) en JavaScript no son realmente matrices en absoluto *, son objetos con un manejo especial para ciertas propiedades, como aquellas cuyos nombres son "índices de matriz" (que son definido como nombres de cadena "... cuyo valor numérico iestá en el rango +0 ≤ i < 2^32-1") y length. Cuando usa deletepara eliminar una entrada de matriz, todo lo que hace es eliminar la entrada; no mueve otras entradas a continuación para llenar el espacio, por lo que la matriz se vuelve "dispersa" (faltan algunas entradas por completo). No tiene ningún efecto sobre length.

Un par de las respuestas actuales a esta pregunta indican incorrectamente que el uso de delete"establece la entrada en undefined". Eso no es correcto Se elimina la entrada (propiedad) por completo, dejando un hueco.

Usemos un código para ilustrar las diferencias:

console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a.splice(0, 1);
console.log(a.length);            // 4
console.log(a[0]);                // "b"

console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
delete a[0];
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // false
console.log(a.hasOwnProperty(0)); // false

console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a[0] = undefined;
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // true
console.log(a.hasOwnProperty(0)); // true


* (esa es una publicación en mi pequeño blog anémico)

TJ Crowder
fuente
2

Actualmente hay dos formas de hacer esto

  1. usando splice ()

    arrayObject.splice(index, 1);

  2. usando eliminar

    delete arrayObject[index];

Pero siempre sugiero usar el empalme para objetos de matriz y eliminar para atributos de objeto porque eliminar no actualiza la longitud de la matriz.

imal hasaranga perera
fuente
1

OK, imagina que tenemos esta matriz a continuación:

const arr = [1, 2, 3, 4, 5];

Hagamos eliminar primero:

delete arr[1];

Y este es el resultado:

[1, empty, 3, 4, 5];

¡vacío! y vamos a obtenerlo:

arr[1]; //undefined

Entonces significa solo el valor eliminado y no está definido ahora, por lo que la longitud es la misma, también devolverá verdadero ...

Vamos a restablecer nuestra matriz y hacerlo con empalme esta vez:

arr.splice(1, 1);

y este es el resultado esta vez:

[1, 3, 4, 5];

Como puede ver, la longitud de la matriz cambió y ahora arr[1]es 3 ...

Además, esto devolverá el elemento eliminado en una matriz que es [3]en este caso ...

Alireza
fuente
1

Otros ya han comparado adecuadamente deletecon splice.

Otra comparación interesante es deleteversus undefined: un elemento de matriz eliminado usa menos memoria que uno que solo está configurado en undefined;

Por ejemplo, este código no terminará:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

Produce este error:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

Entonces, como puede ver, en undefinedrealidad ocupa memoria de montón.

Sin embargo, si también deleteusa el elemento ary (en lugar de simplemente configurarlo undefined), el código terminará lentamente:

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

Estos son ejemplos extremos, pero señalan deleteque no he visto a nadie mencionar en ningún lado.

Lonnie Best
fuente
1

Si tiene una matriz pequeña, puede usar filter:

myArray = ['a', 'b', 'c', 'd'];
myArray = myArray.filter(x => x !== 'b');
Emir Mamashov
fuente
0

La forma más fácil es probablemente

var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1]; // ['a', undefined, 'c', 'd']. Then use lodash compact method to remove false, null, 0, "", undefined and NaN
myArray = _.compact(myArray); ['a', 'c', 'd'];

Espero que esto ayude. Referencia: https://lodash.com/docs#compact

Prashanth
fuente
1
Si alguien tropieza con esta pregunta sobre compact... no hay necesidad de lodash. TratemyArray.filter(function(n){return n;})
dat
0

Para aquellos que quieran usar Lodash pueden usar: myArray = _.without(myArray, itemToRemove)

O como yo uso en Angular2

import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...
Ricky Levi
fuente
0

eliminar : eliminar eliminará la propiedad del objeto, pero no reindexará la matriz ni actualizará su longitud. Esto hace que parezca que no está definido:

empalme : en realidad elimina el elemento, reindexa la matriz y cambia su longitud.

Eliminar elemento del último

arrName.pop();

Eliminar elemento del primero

arrName.shift();

Eliminar del medio

arrName.splice(starting index,number of element you wnt to delete);

Ex: arrName.splice(1,1);

Eliminar un elemento del último

arrName.splice(-1);

Eliminar utilizando el número de índice de la matriz

 delete arrName[1];
Srikrushna
fuente
0

Si el elemento deseado para eliminar está en el medio (digamos que queremos eliminar 'c', cuyo índice es 1), puede usar:

var arr = ['a','b','c'];
var indexToDelete = 1;
var newArray = arr.slice(0,indexToDelete).combine(arr.slice(indexToDelete+1, arr.length))
Idan Gozlan
fuente
0

IndexOfacepta también un tipo de referencia. Supongamos el siguiente escenario:

var arr = [{item: 1}, {item: 2}, {item: 3}];
var found = find(2, 3); //pseudo code: will return [{item: 2}, {item:3}]
var l = found.length;

while(l--) {
   var index = arr.indexOf(found[l])
      arr.splice(index, 1);
   }
   
console.log(arr.length); //1

Diferentemente:

var item2 = findUnique(2); //will return {item: 2}
var l = arr.length;
var found = false;
  while(!found && l--) {
  found = arr[l] === item2;
}

console.log(l, arr[l]);// l is index, arr[l] is the item you look for
Roland
fuente
-1
function deleteFromArray(array, indexToDelete){
  var remain = new Array();
  for(var i in array){
    if(array[i] == indexToDelete){
      continue;
    }
    remain.push(array[i]);
  }
  return remain;
}

myArray = ['a', 'b', 'c', 'd'];
deleteFromArray(myArray , 0);

// resultado: myArray = ['b', 'c', 'd'];

Eyad Farra
fuente
@ChrisDennis ¿por qué? (no se pretende sarcasmo ni malicia, esta es una pregunta sincera)
Chris Bier
Además del hecho de que esta respuesta no responde a la pregunta del OP
Chris Bier