Eliminazione di elementi dell'array in JavaScript: elimina vs splice


1334

Qual è la differenza tra utilizzando l' deleteoperatore sull'elemento matrice anziché utilizzare il Array.splicemetodo ?

Per esempio:

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

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

Perché anche avere il metodo splice se posso eliminare gli elementi dell'array come faccio con gli oggetti?


3
Per .splicenei loop, dai un'occhiata a questa domanda: Elimina dall'array in javascript .
Rob W,

6
@andynormancx Sì, ma questa risposta è stata pubblicata il giorno dopo e ha ottenuto molti più voti - direi che è meglio scrivere, deve essere così.
Camilo Martin,

@andynormancx - Non sembra essere un duplicato esatto. La domanda che hai collegato è in sostanza la domanda sul perché l'eliminazione di un elemento da un array (rendendolo così scarso) non ne ridurrà la lunghezza. Questa domanda richiede le differenze tra deletee Array.prototype.splice.
Chharvey,

@chharvey ha concordato, soprattutto se come può essere stata posta questa domanda 9 anni fa! Mi fa sentire vecchio tornare qui a commentarlo
andynormancx

Risposte:


1693

deleteeliminerà la proprietà dell'oggetto, ma non reindicizzerà l'array né ne aggiornerà la lunghezza. Questo fa apparire come se non fosse definito:

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

Si noti che in realtà non è impostato sul valore undefined, ma la proprietà viene rimossa dall'array, facendolo apparire indefinito. Gli strumenti di sviluppo di Chrome rendono chiara questa distinzione stampando emptyquando si registra l'array.

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

myArray.splice(start, deleteCount) rimuove effettivamente l'elemento, reindicizza l'array e ne modifica la lunghezza.

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]

74
In realtà, delete fa rimuovere l'elemento, ma non reindex la matrice o aggiornare la sua lunghezza (che è già implicata dal precedente poiché la lunghezza è sempre il più alto indice + 1).
Felix Kling,

3
A JSlint non piace la delete myArray[0]sintassi che dice " Previsto un operatore e invece ha visto 'elimina'. " spliceSi consiglia l' utilizzo .
Occhio

21
@Eye: In realtà, JSLint si sta solo lamentando della mancanza di un punto e virgola nella riga precedente. E non puoi davvero consigliarti l'uno sull'altro, dal momento che fanno cose completamente diverse ...
Ry-

3
"Elimina in questo caso imposterà l'elemento solo come non definito:" No, questo è decisamente errato. C'è una differenza fondamentale tra delete myArray[0]e myArray[0] = undefined. Nel primo caso, la proprietà viene completamente rimossa dall'oggetto array. Nel secondo caso, la proprietà rimane, con il valore undefined.
TJ Crowder,

1
Cordiali saluti, gli strumenti di sviluppo di Chrome mostrano la parola chiave emptyinvece di undefinedmigliorare la distinzione tra un elemento array effettivamente cancellato (o non inizializzato) rispetto a un elemento che ha il valore reale di undefined. Si noti che mentre lo dico intendo che viene visualizzato solo come emptye non si riferisce a un valore reale chiamato empty(che non esiste).
Chharvey,

340

Metodo Array.remove ()

John Resig , creatore di jQuery ha creato un Array.removemetodo molto utile che lo uso sempre nei miei progetti.

// 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);
};

ed ecco alcuni esempi di come potrebbe essere usato:

// 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);

Sito Web di John


4
+1 per Array.remove (). Tuttavia non è felice che vengano passati argomenti di stringa (diversamente dalla maggior parte dei metodi Array, ad esempio [1,2,3].slice('1'); // =[2,3]), quindi è più sicuro cambiarlo invar rest = this.slice(parseInt(to || from) + 1 || this.length);
Richard Inglis,

1
@tomwrong, non ci sono thread in javascript e la funzione viene eseguita this.push.apply(this, rest), quindi restituisce il valore restituito
billy

59
Questo non risponde affatto alla domanda.
Ry-

16
Perché non usare solo splice ()? Il nome di questa funzione, i nomi dei parametri e i risultati non sono ovvi. La mia raccomandazione è di usare solo la giuntura (indice, lunghezza) - (vedi la risposta di Andy Hume)
auco

3
La funzione fornita sopra funziona come spiegato, ma crea effetti collaterali indesiderati quando si scorre attraverso array con for(var i in array)ciclo. L'ho rimosso e ho usato invece la giunzione.
alexykot,

104

Poiché delete rimuove solo l'oggetto dall'elemento dell'array, la lunghezza dell'array non cambierà. La giunzione rimuove l'oggetto e accorcia l'array.

Il seguente codice visualizzerà "a", "b", "undefined", "d"

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

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

Considerando che questo mostrerà "a", "b", "d"

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

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

11
ottimo esempio tranne l'ambiguità nel secondo esempio usando 1,1 - il primo 1 si riferisce all'indice nell'array per avviare la giunzione, il secondo 1 è il numero di elementi da rimuovere. Quindi, per rimuovere 'c' dall'array originale, usamyArray.splice(2,1)
iancoleman il

68

Mi sono imbattuto in questa domanda mentre cercavo di capire come rimuovere ogni ricorrenza di un elemento da un array. Ecco un confronto dei splicee deleteper la rimozione di ogni 'c'dalla itemsmatrice.

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"]


10

splice funzionerà con indici numerici.

mentre delete può essere usato contro altri tipi di indici ..

esempio:

delete myArray['text1'];

9
Quando dite "qualsiasi altro tipo di indici", non state più parlando di array, ma piuttosto di oggetti, che è ciò di cui l'OP sta chiedendo.
Yi Jiang,

2
@YiJiang: le matrici sono oggetti. Gli indici sono proprietà. Non c'è differenza.
Bergi,

9

Probabilmente vale anche la pena ricordare che la giunzione funziona solo su array. (Non è possibile fare affidamento sulle proprietà degli oggetti per seguire un ordine coerente.)

Per rimuovere la coppia chiave-valore da un oggetto, eliminare è effettivamente ciò che desideri:

delete myObj.propName;     // , or:
delete myObj["propName"];  // Equivalent.

delete non riordina le chiavi dell'array, quindi: var arr = [1,2,3,4,5]; elimina arr [3]; per (var i = 0; i <= arr.length; i ++) console.log (arr [i]); mostrerà risultati inaspettati.
Kristian Williams,

Questo è vero. Quindi, a meno che tu non voglia lasciare un oggetto indefinito in quella posizione, NON usare elimina sulle chiavi di un array! Inizialmente ho aggiunto questo commento per includere un riferimento sull'uso corretto dell'eliminazione.
jtrick,

ma perché eliminare genererà risultati inaspettati ??
Alex,

9

elimina Vs splice

quando si elimina un elemento da un array

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

quando si giunge

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

in caso di cancellazione l' elemento viene cancellato ma l' indice rimane vuoto

mentre in caso di elemento di giunzione viene eliminato e l' indice degli elementi di riposo viene ridotto di conseguenza


8

Come affermato molte volte sopra, l'utilizzo splice()sembra perfetto. Documentazione su Mozilla:

Il splice()metodo modifica il contenuto di un array rimuovendo elementi esistenti e / o aggiungendo nuovi elementi.

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"]

Sintassi

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

parametri

inizio

Indice da cui iniziare a modificare l'array. Se maggiore della lunghezza dell'array, l'indice iniziale effettivo verrà impostato sulla lunghezza dell'array. Se negativo, inizierà così tanti elementi dalla fine.

deleteCount

Un numero intero che indica il numero di vecchi elementi dell'array da rimuovere. Se deleteCount è 0, nessun elemento viene rimosso. In questo caso, è necessario specificare almeno un nuovo elemento. Se deleteCount è maggiore del numero di elementi rimasti nell'array a partire dall'inizio, tutti gli elementi fino alla fine dell'array verranno eliminati.

Se si elimina deleteCount, deleteCount sarà uguale a (arr.length - start).

oggetto1, oggetto2, ...

Gli elementi da aggiungere all'array, iniziando dall'indice iniziale. Se non specifichi alcun elemento,splice() verranno rimossi solo gli elementi dall'array.

Valore di ritorno

Un array contenente gli elementi eliminati. Se viene rimosso solo un elemento, viene restituita una matrice di un elemento. Se non vengono rimossi elementi, viene restituita una matrice vuota.

[...]


@downvoter: perché il downvote? ti interessa spiegare o no?
serv-inc

7

delete si comporta come una situazione non reale, rimuove semplicemente l'elemento, ma la lunghezza dell'array rimane la stessa:

esempio dal terminale del nodo:

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

Ecco una funzione per rimuovere un elemento di un array per indice, usando slice () , prende arr come primo argomento e l'indice del membro che si desidera cancellare come secondo argomento. Come puoi vedere, elimina effettivamente il membro dell'array e ridurrà la lunghezza dell'array di 1

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

Ciò che fa la funzione sopra è portare tutti i membri all'indice e tutti i membri dopo l'indice, li concatena insieme e restituisce il risultato.

Ecco un esempio usando la funzione sopra come modulo di nodo, vedere il terminale sarà utile:

> 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

si noti che questo non funzionerà un array con duplicati in esso, perché indexOf ("c") otterrà solo la prima occorrenza e si separerà e rimuoverà solo la prima "c" che trova.


6

Se si desidera iterare un array di grandi dimensioni ed eliminare selettivamente gli elementi, sarebbe costoso chiamare splice () per ogni eliminazione poiché splice () dovrebbe reindicizzare gli elementi successivi ogni volta. Poiché gli array sono associativi in ​​Javascript, sarebbe più efficiente eliminare i singoli elementi e quindi reindicizzare l'array in seguito.

Puoi farlo costruendo un nuovo array. per esempio

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

Ma non penso che tu possa modificare i valori chiave nell'array originale, il che sarebbe più efficiente - sembra che potresti dover creare un nuovo array.

Si noti che non è necessario controllare le voci "non definite" in quanto in realtà non esistono e il ciclo for non le restituisce. È un artefatto della stampa di array che li visualizza come non definiti. Non sembrano esistere nella memoria.

Sarebbe bello se potessi usare qualcosa come slice () che sarebbe più veloce, ma non reindicizza. Qualcuno sa di un modo migliore?


In realtà, probabilmente puoi farlo sul posto come segue, che è probabilmente più efficiente, dal punto di vista delle prestazioni:

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)
},

Credo che l'indice ++; deve accadere al di fuori del "se". Modifica
mishal153

6

puoi usare qualcosa del genere

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]


questo è più intuitivo che slicese vieni da un background funzionale (probabilmente meno efficiente, però).
jethro,

3

Perché non solo filtrare? Penso che sia il modo più chiaro di considerare gli array in js.

myArray = myArray.filter(function(item){
    return item.anProperty != whoShouldBeDeleted
});

Che dire di un array con centinaia (se non migliaia) di record in cui solo 3 di essi devono essere rimossi?
Joel Hernandez,

buon punto. io uso questo metodo per array sparsi la cui lunghezza non è superiore a 200 o 300 e funziona molto bene. Tuttavia, penso che le biblioteche come sottolineate dovrebbero essere preferite se si devono gestire array così grandi.
Asqan,

1
Tuttavia, sembra molto più bello di deleteo sliceper me.
Juneyoung Oh,

3

La differenza può essere vista registrando la lunghezza di ciascun array dopo l'applicazione deletedell'operatore e del splice()metodo. Per esempio:

cancella operatore

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

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

L' deleteoperatore rimuove l'elemento dall'array, ma il "segnaposto" dell'elemento esiste ancora. oakè stato rimosso ma occupa ancora spazio nell'array. Per questo motivo, la lunghezza dell'array rimane 5.

metodo splice ()

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

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

Il splice()metodo rimuove completamente anche il valore target e il "segnaposto". oakè stato rimosso e lo spazio utilizzato per occupare l'array. La lunghezza dell'array è ora 4.


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;
}

esempio:

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

la banana viene eliminata e la lunghezza dell'array = 2


2

Sono cose diverse che hanno scopi diversi.

spliceè specifico dell'array e, quando utilizzato per l'eliminazione, rimuove le voci dall'array e sposta tutte le voci precedenti verso l'alto per riempire il vuoto. (Può anche essere usato per inserire voci, o entrambi contemporaneamente.) spliceCambierà lengthl'array (supponendo che non sia una chiamata no-op:) theArray.splice(x, 0).

deletenon è specifico dell'array; è progettato per l'uso sugli oggetti: rimuove una proprietà (coppia chiave / valore) dall'oggetto su cui la usi. Si applica solo agli array perché gli array standard (ad esempio, non tipizzati) in JavaScript non sono affatto array *, sono oggetti con una gestione speciale per determinate proprietà, come quelli i cui nomi sono "indici array" (che sono definito come nomi di stringa "... il cui valore numerico iè compreso nell'intervallo +0 ≤ i < 2^32-1") e length. Quando si utilizza deleteper rimuovere una voce dell'array, tutto ciò che fa è rimuovere la voce; non sposta altre voci che lo seguono per riempire il vuoto, quindi l'array diventa "rado" (alcune voci mancano del tutto). Non ha alcun effettolength .

Un paio delle risposte attuali a questa domanda indicano erroneamente che l'utilizzo di delete"imposta la voce su undefined". Non è corretto si rimuove la voce (proprietà) del tutto, lasciando un vuoto.

Usiamo un po 'di codice per illustrare le differenze:

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


* (è un post sul mio anemico piccolo blog)


2

Attualmente ci sono due modi per farlo

  1. usando splice ()

    arrayObject.splice(index, 1);

  2. usando Elimina

    delete arrayObject[index];

Ma suggerisco sempre di usare la giunzione per gli oggetti dell'array e di eliminare gli attributi degli oggetti perché delete non aggiorna la lunghezza dell'array.


1

OK, immagina di avere questo array qui sotto:

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

Cancella prima:

delete arr[1];

e questo è il risultato:

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

vuoto! e prendiamolo:

arr[1]; //undefined

Quindi significa solo il valore eliminato e ora non è definito , quindi la lunghezza è la stessa, inoltre restituirà vero ...

Ripristiniamo il nostro array e lo facciamo con splice questa volta:

arr.splice(1, 1);

e questo è il risultato questa volta:

[1, 3, 4, 5];

Come vedi la lunghezza dell'array è cambiata ed arr[1]è 3 ora ...

Anche questo restituirà l'elemento eliminato in un array che è [3]in questo caso ...


1

Altri hanno già confrontato correttamente deleteconsplice .

Un altro confronto interessante è deletecontro undefined: un elemento di array eliminato usa meno memoria di uno appena impostato undefined;

Ad esempio, questo codice non finirà:

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 questo errore:

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

Quindi, come puoi vedere, undefinedoccupa davvero memoria dell'heap.

Tuttavia, se hai anche deletel'oggetto ary (invece di impostarlo su undefined), il codice finirà 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}.`);

Questi sono esempi estremi, ma sottolineano deleteche non ho visto nessuno menzionare da nessuna parte.


1

Se hai un array piccolo puoi usare filter:

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

0

Il modo più semplice è probabilmente

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'];

Spero che sia di aiuto. Riferimento: https://lodash.com/docs#compact


1
Qualcuno dovrebbe inciampare in questa domanda su compact... non c'è bisogno di lodash. ProvamyArray.filter(function(n){return n;})
dat

0

Per coloro che vogliono usare Lodash possono usare: myArray = _.without(myArray, itemToRemove)

O come uso in Angular2

import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...

0

delete : delete cancella la proprietà dell'oggetto, ma non reindicizza l'array né ne aggiorna la lunghezza. Questo fa apparire come se non fosse definito:

splice : rimuove effettivamente l'elemento, reindicizza l'array e ne modifica la lunghezza.

Elimina l'elemento dall'ultimo

arrName.pop();

Elimina l'elemento dal primo

arrName.shift();

Elimina dal centro

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

Ex: arrName.splice(1,1);

Elimina un elemento dall'ultimo

arrName.splice(-1);

Eliminare utilizzando il numero indice dell'array

 delete arrName[1];

0

Se l'elemento desiderato da eliminare è nel mezzo (supponiamo di voler eliminare 'c', il cui indice è 1), è possibile utilizzare:

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

0

IndexOfaccetta anche un tipo di riferimento. Supponiamo che il seguente scenario:

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

diversamente:

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

-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);

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


@ChrisDennis perché? (nessun sarcasmo o malizia intesi, questa è una domanda sincera)
Chris Bier,

Oltre al fatto che questa risposta non risponde alla domanda del PO
Chris Bier,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.