Come rimuovo gli oggetti da un array associativo javascript?


619

Supponiamo di avere questo codice:

var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

Ora, se volessi rimuovere "lastname"? .... c'è qualche equivalente di
myArray["lastname"].remove()?

(Ho bisogno che l'elemento sparisca perché il numero di elementi è importante e voglio mantenere le cose pulite.)


27
Un consiglio: non confondere array e mappe. Alcune lingue, come php, hanno un singolo oggetto per entrambi. Sebbene tu abbia usato il tipo giusto qui (new Object ()), l'hai chiamato myArray, è solo una questione di standard per una lingua.
Juan Mendes,

Non dimenticare che JavaScript è senza tipo e tutto è un oggetto. Vedi la risposta di Saul sotto.
stevek,

4
@StephanKristyn - per essere precisi, JS ha tipi ma in modo dinamico e debole . Ad esempio, mentre le sue variabili sono davvero senza tipo, i loro valori no. Questa è la parte dinamica . Debole indica che le operazioni tra diversi tipi di valore non sono strettamente definite e si basano su conversioni dietro le quinte; per esempio "Test" + {};è una dichiarazione JS perfettamente valida.
Saul

Risposte:


1135

Gli oggetti in JavaScript possono essere pensati come array associativi, mappando chiavi (proprietà) su valori.

Per rimuovere una proprietà da un oggetto in JavaScript si utilizza l' deleteoperatore:

const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false

Si noti che quando deleteviene applicato a una proprietà di indice di un Array, verrà creato un array scarsamente popolato (cioè un array con un indice mancante).

Quando si lavora con istanze di Array, se non si desidera creare un array scarsamente popolato - e di solito non lo si fa - è necessario utilizzare Array#spliceo Array#pop.

Si noti che l' deleteoperatore in JavaScript non libera direttamente la memoria. Il suo scopo è rimuovere le proprietà dagli oggetti. Ovviamente, se una proprietà che viene eliminata contiene l'unico riferimento rimanente a un oggetto o, osuccessivamente verrà spazzatura raccolta in modo normale.

L'uso deletedell'operatore può influire sulla capacità dei motori JavaScript di ottimizzare il codice .


18
Ciò causerà problemi se utilizzato su un'istanza di un oggetto Array per rimuovere un elemento esistente, ad es delete myArray[0]. Vedi stackoverflow.com/a/9973592/426379 e Eliminazione di elementi dell'array
Saul

4
Quali problemi saranno causati?
Gottox,

26
@Gottox - La lengthproprietà di un oggetto Array rimane invariata.
Saul,

12
@Saul: ci sarebbero problemi se myArrayfosse davvero usato come un array - ma non lo è ( myArrayè un nome sfortunato), è un oggetto. Quindi in questo caso deleteva bene. Si noti che anche se fosse stato creato new Array()e utilizzato come array associativo sarebbe comunque OK. Il tuo avvertimento è ancora qualcosa di cui essere consapevoli se si utilizzano array reali.
johndodo,

2
@johndodo - True. Ecco perché ho iniziato il mio commento iniziale con Ciò causerà problemi se utilizzato su un'istanza di oggetto Array . Preferisco comunque un approccio che funzioni correttamente in tutti i casi, vedere la mia risposta di seguito.
Saul

79

Tutti gli oggetti in JavaScript sono implementati come array hashtables / associativi. Quindi, i seguenti sono l'equivalente:

alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);

E, come già indicato, "rimuovi" una proprietà da un oggetto tramite la deleteparola chiave, che puoi utilizzare in due modi:

delete myObj["SomeProperty"];
delete myObj.SomeProperty;

Spero che le informazioni extra aiutino ...


10
va notato che la notazione punto non funziona se la proprietà non è un termine semplice. cioè myObj['some;property']funziona, ma myObj.some;propertynon lo farebbe (per ovvi motivi). Inoltre, potrebbe non essere ovvio che è possibile utilizzare una variabile nella notazione tra parentesi, ovverovar x = 'SomeProperty'; alert(myObj[x])
Kip

2
"Tutti gli oggetti in JavaScript sono implementati come array hashtables / associativi." - false. V8 preferisce archiviare un oggetto come classe nascosta + campi densi. Solo se fai cose strane (come rimuovere i campi) si arrende e usa una mappa hash dietro le quinte.
John Dvorak,

4
@JanDvorak - hey, riconosci quando questa risposta è stata scritta originariamente, sì? Tale descrizione era ed è ancora sufficiente per la maggior parte degli scopi. Detto questo, capisco di essere noiosamente pedante. :)
Jason Bunting,

41

Nessuna delle risposte precedenti affronta il fatto che Javascript non ha matrici associative per cominciare - non esiste un arraytipo in quanto tale, vedi typeof.

Ciò che Javascript ha sono istanze di oggetti con proprietà dinamiche. Quando le proprietà vengono confuse con gli elementi di un'istanza di un oggetto Array, allora Bad Things ™ deve accadere:

Problema

var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log("number of elements: ", elements.length)   // returns 2
delete elements[1]
console.log("number of elements: ", elements.length)   // returns 2 (?!)

for (var i = 0; i < elements.length; i++)
{
   // uh-oh... throws a TypeError when i == 1
   elements[i].onmouseover = function () { window.alert("Over It.")}
   console.log("success at index: ", i)
}

Soluzione

Per avere una funzione di rimozione universale che non ti esplode, usa:

Object.prototype.removeItem = function (key) {
   if (!this.hasOwnProperty(key))
      return
   if (isNaN(parseInt(key)) || !(this instanceof Array))
      delete this[key]
   else
      this.splice(key, 1)
};

//
// Code sample.
//
var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log(elements.length)                        // returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.log(elements.hasOwnProperty("prop"))        // returns false as it should
console.log(elements.length)                        // returns 1 as it should

8
Questa soluzione ha due problemi: nasconde il fatto che matrici e oggetti siano bestie completamente diverse in JS (lo sai, ma a quanto pare OP non lo fa) e usa prototipi. OP starebbe meglio se venisse a conoscenza di matrici e oggetti (e nominerebbe le sue variabili di conseguenza) - cercare di nascondere le differenze tra i due non lo farà avere più problemi. IMHO ovviamente.
johndodo,

1
@johndodo - tutti gli Arrays in JS sono oggetti, prova typeof new Array();o typeof []verifica. Arrayè semplicemente un certo tipo di oggetto e non è affatto una "bestia diversa". In JS, gli oggetti si distinguono per il nome del costruttore e la catena del prototipo, vedere Programmazione basata su prototipo .
Saul

9
Ti manca il punto. So che anche gli array sono oggetti, ma ciò non significa che sia saggio usarli come tali. Il programmatore dovrebbe decidere se vuole usare qualcosa come array (con push, pop, [], ...) o come oggetto / "array associativo". Il mix and match non è una buona ricetta, proprio a causa dei problemi che la tua soluzione sta cercando di nascondere. Se si decide in anticipo quale modello di progettazione utilizzare (array o oggetto) non si verificheranno tali problemi.
johndodo,

7
@johndodo - Di quali problemi stai parlando in particolare? Lo scopo del codice sopra è di indirizzare l' deleteoperatore di carenza rispetto a Arrayfornire una semplice funzione polimorfica.
Saul

1
deletenon ha un difetto. deleteè progettato per rimuovere le proprietà. Questo è tutto. L'applicazione dell'operatore di eliminazione a un indice di un array rimuove tale indice. Cosa serve di più? Ti rimane un array sparso, che è una caratteristica della lingua. Se non si desidera un array sparse, non eliminare l'indice: utilizzare spliceo pop.
Ben Aston,

35

Ciò rimuove solo l'eliminazione dell'oggetto ma mantiene comunque la stessa lunghezza dell'array.

Per rimuovere devi fare qualcosa come:

array.splice(index, 1);

11
Anzi, ma in questo caso non viene utilizzato un array, ma solo un semplice oggetto vecchio, quindi non ha un metodo lunghezza o giunzione.
MooGoo,

2
@Andreaa Panagiotidis Tranne quando non stiamo parlando di array, nel qual caso è sbagliato il 100% delle volte 🙂
Drenai,

17

Mentre la risposta accettata è corretta, manca la spiegazione del perché funziona.

Prima di tutto, il tuo codice dovrebbe riflettere il fatto che questo NON è un array:

var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;

Si noti che tutti gli oggetti (inclusi quelli Array) possono essere utilizzati in questo modo. Tuttavia, non aspettarti che funzioni standard dell'array JS (pop, push, ...) funzionino sugli oggetti!

Come detto nella risposta accettata, è quindi possibile utilizzare deleteper rimuovere le voci dagli oggetti:

delete myObject["lastname"]

Dovresti decidere quale percorso vuoi prendere - usa gli oggetti (array / dizionari associativi) o usa gli array (mappe). Non mescolare mai i due.


6
Ottima risposta Consiglio a chiunque legga questo che gli array in javascript non dovrebbero essere astratti come "mappe", ma piuttosto "elenchi". Questo perché non dovresti provare ad avere il controllo sull'indice degli elementi quando usi le matrici. Se ci provi ... beh, non farlo: D
rodolfo42

6

Utilizzare il metodo spliceper rimuovere completamente l'elemento da una matrice di oggetti:

Object.prototype.removeItem = function (key, value) {
    if (value == undefined)
        return;

    for (var i in this) {
        if (this[i][key] == value) {
            this.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");

1
questa è una soluzione più generica, può essere aggiunta al tuo file js e il metodo sarà disponibile per tutti gli array, non solo per un array.
Hussain,

6

Come hanno notato altre risposte, quello che stai usando non è un array Javascript, ma un oggetto Javascript, che funziona quasi come un array associativo in altre lingue, tranne per il fatto che tutte le chiavi vengono convertite in stringhe. La nuova mappa memorizza le chiavi come il loro tipo originale.

Se si disponesse di un array e non di un oggetto, è possibile utilizzare la funzione .filter dell'array per restituire un nuovo array senza l'elemento che si desidera rimuovere:

var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
    return item !== 'Smith';
});

Se hai un browser più vecchio e jQuery, jQuery ha un $.grepmetodo che funziona in modo simile:

myArray = $.grep(myArray, function(item) {
    return item !== 'Smith';
});

spiegazione perfetta. Ho usato il filtro per ottenere il risultato desiderato. Spiegheresti come funziona l'elemento return per rimuovere l'oggetto dall'array. Suppongo che restituisca l'array a condizione che non includa la stringa inclusa.
Edward,


5

Stai usando Object, non hai un array associativo per cominciare. Con un array associativo, l'aggiunta e la rimozione di elementi avviene in questo modo:

    Array.prototype.contains = function(obj) 
    {
        var i = this.length;
        while (i--) 
        {
            if (this[i] === obj) 
            {
                return true;
            }
        }
        return false;
    }


    Array.prototype.add = function(key, value) 
    {
        if(this.contains(key))
            this[key] = value;
        else
        {
            this.push(key);
            this[key] = value;
        }
    }


    Array.prototype.remove = function(key) 
    {
        for(var i = 0; i < this.length; ++i)
        {
            if(this[i] == key)
            {
                this.splice(i, 1);
                return;
            }
        }
    }



    // Read a page's GET URL variables and return them as an associative array.
    function getUrlVars()
    {
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }

        return vars;
    }



    function ForwardAndHideVariables() {
        var dictParameters = getUrlVars();

        dictParameters.add("mno", "pqr");
        dictParameters.add("mno", "stfu");

        dictParameters.remove("mno");



        for(var i = 0; i < dictParameters.length; i++)
        {
            var key = dictParameters[i];
            var value = dictParameters[key];
            alert(key + "=" + value);
        }
        // And now forward with HTTP-POST
        aa_post_to_url("Default.aspx", dictParameters);
    }


    function aa_post_to_url(path, params, method) {
        method = method || "post";

        var form = document.createElement("form");

        //move the submit function to another variable
        //so that it doesn't get written over if a parameter name is 'submit'
        form._submit_function_ = form.submit;

        form.setAttribute("method", method);
        form.setAttribute("action", path);

        for(var i = 0; i < params.length; i++)
        {
            var key = params[i];

            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }

        document.body.appendChild(form);
        form._submit_function_(); //call the renamed function
    }

4

Puoi rimuovere una voce dalla tua mappa assegnandola esplicitamente a "non definito". Come nel tuo caso:

myArray ["lastname"] = undefined;


Questo potrebbe essere utile nei casi in cui non si è sicuri che la chiave esista nel dizionario, ma si desidera disinfettarla nel caso in cui lo faccia. Correggimi se sbaglio Amytis.
Hassan Baig,

3

Se per qualsiasi motivo la chiave di eliminazione non funziona (come se non funzionasse per me)

È possibile separarlo e quindi filtrare i valori non definiti

// to cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});

Non provare a incatenarli poiché la giunzione restituisce elementi rimossi;


3

Possiamo usarlo anche come funzione. Angular genera un errore se usato come prototipo. Grazie @HarpyWar. Mi ha aiutato a risolvere un problema.

var removeItem = function (object, key, value) {
    if (value == undefined)
        return;

    for (var i in object) {
        if (object[i][key] == value) {
            object.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

removeItem(collection, "id", "87353080-8f49-46b9-9281-162a41ddb8df");


1

Usando la "delete"parola chiave, eliminerà l'elemento array dall'array in javascript.

Per esempio,

Prendi in considerazione le seguenti dichiarazioni.

var arrayElementToDelete = new Object();

arrayElementToDelete["id"]           = "XERTYB00G1"; 
arrayElementToDelete["first_name"]   = "Employee_one";
arrayElementToDelete["status"]       = "Active"; 

delete arrayElementToDelete["status"];

L'ultima riga del codice rimuoverà l'elemento dell'array la cui chiave è "status" dall'array.


0
var myArray = newmyArray = new Object(); 
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

var s = JSON.stringify(myArray);

s.replace(/"lastname[^,}]+,/g,'');
newmyArray = JSON.parse(p);

Senza loop / iterate otteniamo lo stesso risultato


0

Per "Array":

Se conosci l'indice:

array.splice(index, 1);

Se conosci il valore:

function removeItem(array, value) {
    var index = array.indexOf(value);
    if (index > -1) {
        array.splice(index, 1);
    }
    return array;
}

La risposta più votata per deletefunziona bene in caso di oggetti ma non per le vere matrici. Se lo uso deleterimuove gli elementi dai loop ma mantiene l'elemento come emptye la lunghezza dell'array non cambierà. Questo può essere un problema in alcuni scenari.

Ad esempio, se faccio myArray.toString () su myArray dopo la rimozione tramite deleteesso crea una voce vuota, cioè ,,


0

L'unico metodo di lavoro per me:

function removeItem (array, value) {
    var i = 0;
    while (i < array.length) {
        if(array[i] === value) {
            array.splice(i, 1);
        } else {
            ++i;
        }
    }
    return array;
}

utilizzo:

var new = removeItem( ["apple","banana", "orange"],  "apple");
// ---> ["banana", "orange"]

Perché non utilizzare invece il filtro? questo è un caso d'uso perfetto per il filtro
Codice Maniac
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.