Wie entferne ich Objekte aus einem assoziativen Javascript-Array?

619

Angenommen, ich habe diesen Code:

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

Wenn ich nun "Nachname" entfernen wollte? .... gibt es ein Äquivalent von
myArray["lastname"].remove()?

(Ich brauche das Element weg, weil die Anzahl der Elemente wichtig ist und ich die Dinge sauber halten möchte.)

djot
quelle
27
Ein Tipp: Verwechseln Sie Arrays und Karten nicht. Einige Sprachen, wie PHP, haben ein einziges Objekt für beide. Obwohl Sie hier den richtigen Typ verwendet haben (neues Objekt ()), haben Sie ihn myArray genannt, aber es ist nur eine Frage der Standards für eine Sprache.
Juan Mendes
Vergessen Sie nicht, dass JavaScript typlos ist und alles ein Objekt ist. Siehe Sauls Antwort unten.
Stevek
4
@StephanKristyn - um genau zu sein, JS hat Typen, aber auf dynamische und schwache Weise. Während seine Variablen tatsächlich typenlos sind, sind ihre Werte dies nicht. Das ist der dynamische Teil. Schwach bedeutet, dass Operationen zwischen verschiedenen Werttypen nicht streng definiert sind und auf Konvertierungen hinter den Kulissen beruhen. Zum Beispiel "Test" + {};ist eine perfekt gültige JS-Anweisung.
Saul

Antworten:

1135

Objekte in JavaScript können als assoziative Arrays betrachtet werden, die Schlüssel (Eigenschaften) Werten zuordnen.

Um eine Eigenschaft aus einem Objekt in JavaScript zu entfernen, verwenden Sie den deleteOperator:

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

Beachten Sie, dass Sie beim deleteAnwenden auf eine Indexeigenschaft von ein dünn besiedeltes ArrayArray erstellen (dh ein Array mit einem fehlenden Index).

Wenn Sie mit Instanzen von arbeiten Arrayund kein dünn besiedeltes Array erstellen möchten - und dies normalerweise nicht -, sollten Sie Array#spliceoder verwenden Array#pop.

Beachten Sie, dass der deleteOperator in JavaScript den Speicher nicht direkt freigibt. Der Zweck besteht darin, Eigenschaften von Objekten zu entfernen. Wenn eine zu löschende Eigenschaft den einzigen verbleibenden Verweis auf ein Objekt enthält o, owird der Müll anschließend auf normale Weise gesammelt.

Die Verwendung von deleteOperator kann JavaScript - Engine die Fähigkeit beeinflussen optimize Code .

Dennis C.
quelle
18
Dies führt zu Problemen, wenn eine Array-Objektinstanz zum Entfernen eines vorhandenen Elements verwendet wird, z delete myArray[0]. Siehe stackoverflow.com/a/9973592/426379 und Löschen von Array-Elementen
Saul
4
Welche Probleme werden verursacht?
Gottox
26
@Gottox - Die lengthEigenschaft eines Array-Objekts bleibt unverändert.
Saul
12
@Saul: Es würde Probleme geben, wenn myArrayes wirklich als Array verwendet würde - aber es ist kein ( myArrayunglücklicher Name), es ist ein Objekt. In diesem Fall deleteist es also in Ordnung. Beachten Sie, dass es auch dann new Array()in Ordnung ist , wenn es als assoziatives Array erstellt und verwendet wird. Ihre Warnung ist immer noch zu beachten, wenn Sie echte Arrays verwenden.
Johndodo
2
@ Johndodo - Stimmt. Aus diesem Grund habe ich meinen ersten Kommentar mit gestartet. Dies führt zu Problemen, wenn es auf einer Array- Objektinstanz verwendet wird . Ich bevorzuge dennoch einen Ansatz, der in allen Fällen korrekt funktioniert, siehe meine Antwort unten.
Saul
79

Alle Objekte in JavaScript werden als Hashtabellen / assoziative Arrays implementiert. Das Folgende ist also das Äquivalent:

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

Und wie bereits erwähnt, "entfernen" Sie eine Eigenschaft aus einem Objekt über das deleteSchlüsselwort, das Sie auf zwei Arten verwenden können:

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

Hoffe die zusätzlichen Infos helfen ...

Jason Bunting
quelle
10
Es ist zu beachten, dass die Punktnotation nicht funktioniert, wenn die Eigenschaft kein einfacher Begriff ist. dh myObj['some;property']funktioniert, myObj.some;propertywürde aber nicht (aus offensichtlichen Gründen). Es ist auch möglicherweise nicht offensichtlich, dass Sie eine Variable in der Klammer-Notation verwenden können, dhvar x = 'SomeProperty'; alert(myObj[x])
Kip
2
"Alle Objekte in JavaScript sind als Hashtabellen / assoziative Arrays implementiert." - false. V8 bevorzugt es, ein Objekt als versteckte Klasse + dicht gepackte Felder zu speichern. Nur wenn Sie seltsame Dinge mit ihnen machen (z. B. Felder entfernen), gibt es auf und verwendet eine Hash-Karte hinter den Kulissen.
John Dvorak
4
@ JanDvorak - hey, du erkennst, wann diese Antwort ursprünglich geschrieben wurde, ja? Diese Beschreibung war und ist für die meisten Zwecke ausreichend. Trotzdem verstehe ich, dass ich mühsam pedantisch bin. :)
Jason Bunting
41

Keine der vorherigen Antworten befasst sich mit der Tatsache, dass Javascript zunächst keine assoziativen Arrays hat - es gibt keinen arrayTyp als solchen, siehe typeof.

Was Javascript hat, sind Objektinstanzen mit dynamischen Eigenschaften. Wenn Eigenschaften mit Elementen einer Array-Objektinstanz verwechselt werden, muss Bad Things ™ passieren:

Problem

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

Lösung

Verwenden Sie: Eine universelle Entfernungsfunktion, die Sie nicht in die Luft jagt:

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
Saul
quelle
8
Diese Lösung weist zwei Probleme auf: Sie verbirgt die Tatsache, dass Arrays und Objekte in JS völlig unterschiedliche Bestien sind (Sie wissen es, aber anscheinend nicht OP) und verwendet Prototypen. OP wäre besser dran, wenn er etwas über Arrays und Objekte lernen würde (und seine Variablen entsprechend benennen würde) - der Versuch, die Unterschiede zwischen den beiden zu verbergen, würde ihn nur in größere Schwierigkeiten bringen. IMHO natürlich.
Johndodo
1
@johndodo - alle Arrays in JS sind Objekte, versuchen Sie typeof new Array();oder typeof []überprüfen Sie. Arrayist einfach eine bestimmte Art von Objekt und überhaupt kein "anderes Tier". In JS werden Objekte durch ihren Konstruktornamen und ihre Prototypkette unterschieden (siehe Prototypbasierte Programmierung) .
Saul
9
Sie verpassen den Punkt. Ich weiß, dass Arrays auch Objekte sind, aber das bedeutet nicht, dass es ratsam ist, sie als solche zu verwenden. Der Programmierer sollte entscheiden, ob er etwas als Array (mit Push, Pop, [], ...) oder als Objekt / "assoziatives Array" verwenden möchte. Mix and Match ist kein gutes Rezept, gerade wegen der Probleme, die Ihre Lösung zu verbergen versucht. Wenn Sie im Voraus entscheiden, welches Entwurfsmuster (Array oder Objekt) verwendet werden soll, treten keine derartigen Probleme auf.
Johndodo
7
@johndodo - Über welche Probleme sprichst du konkret? Der Zweck des obigen Codes besteht darin, den Mangeloperator deletein Bezug auf die ArrayBereitstellung einer einfachen polymorphen Funktion anzusprechen .
Saul
1
deletehat keinen Mangel. deletedient zum Entfernen von Eigenschaften. Das ist es. Durch Anwenden des Löschoperators auf einen Index eines Arrays wird dieser Index entfernt. Was muss es noch tun? Sie haben ein spärliches Array, das ein Merkmal der Sprache ist. Wenn Sie kein Array mit geringer Dichte möchten, löschen Sie den Index nicht: use spliceor pop.
Ben Aston
35

Durch das Entfernen wird nur das Objekt gelöscht, die Array-Länge bleibt jedoch gleich.

Zum Entfernen müssen Sie Folgendes tun:

array.splice(index, 1);
Bipin
quelle
11
In der Tat, aber in diesem Fall wird kein Array verwendet, sondern nur ein einfaches altes Objekt, daher hat es keine Längen- oder Spleißmethode.
MooGoo
2
@Andreaa Panagiotidis Außer wenn wir nicht über Arrays sprechen, in diesem Fall ist es 100% der Zeit falsch 🙂
Drenai
17

Während die akzeptierte Antwort korrekt ist, fehlt die Erklärung, warum sie funktioniert.

Zunächst sollte Ihr Code die Tatsache widerspiegeln, dass dies KEIN Array ist:

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

Beachten Sie, dass alle Objekte (einschließlich Arrays) auf diese Weise verwendet werden können. Erwarten Sie jedoch nicht, dass Standard-JS-Array-Funktionen (Pop, Push, ...) an Objekten funktionieren!

Wie in der akzeptierten Antwort angegeben, können Sie dann deletedie Einträge von Objekten entfernen:

delete myObject["lastname"]

Sie sollten entscheiden, welche Route Sie nehmen möchten - entweder Objekte (assoziative Arrays / Wörterbücher) oder Arrays (Karten) verwenden. Mischen Sie niemals die beiden.

Johndodo
quelle
6
Sehr gute Antwort. Ich würde jedem, der dies liest, nur raten, dass Arrays in Javascript nicht als "Karten", sondern als "Listen" abstrahiert werden sollten. Dies liegt daran, dass Sie bei der Verwendung von Arrays nicht versuchen sollten, die Kontrolle über den Index der Elemente zu haben. Wenn Sie das versuchen ... nun, tun Sie es einfach nicht: D
rodolfo42
6

Verwenden Sie die Methode splice, um Elemente vollständig aus einem Objektarray zu entfernen:

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");
Harpyie
quelle
1
Dies ist eine allgemeinere Lösung, die zu Ihrer JS-Datei hinzugefügt werden kann und die Methode für alle Arrays verfügbar ist, nicht nur für ein Array.
Hussain
6

Wie andere Antworten bereits festgestellt haben, verwenden Sie kein Javascript-Array, sondern ein Javascript-Objekt, das in anderen Sprachen fast wie ein assoziatives Array funktioniert, mit der Ausnahme, dass alle Schlüssel in Zeichenfolgen konvertiert werden. Die neue Karte speichert Schlüssel als ihren ursprünglichen Typ.

Wenn Sie ein Array und kein Objekt hatten, können Sie die Filterfunktion des Arrays verwenden , um ein neues Array ohne das zu entfernende Element zurückzugeben:

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

Wenn Sie einen älteren Browser und jQuery haben, verfügt jQuery über eine $.grepMethode , die ähnlich funktioniert:

myArray = $.grep(myArray, function(item) {
    return item !== 'Smith';
});
Dzeimsas Zvirblis
quelle
perfekte Erklärung. Ich habe Filter verwendet, um das gewünschte Ergebnis zu erzielen. Würden Sie erklären, wie das Rückgabeelement funktioniert, um das Objekt aus dem Array zu entfernen? Ich gehe davon aus, dass es das Array zurückgibt, solange es nicht die von Ihnen eingeschlossene Zeichenfolge enthält.
Edward
5

Wenn Sie Object verwenden, haben Sie zunächst kein assoziatives Array. Bei einem assoziativen Array sieht das Hinzufügen und Entfernen von Elementen folgendermaßen aus:

    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
    }
Stefan Steiger
quelle
4

Sie können einen Eintrag aus Ihrer Karte entfernen, indem Sie ihn explizit 'undefined' zuweisen. Wie in Ihrem Fall:

myArray ["Nachname"] = undefiniert;

Amytis
quelle
Dies kann in Fällen nützlich sein, in denen man nicht sicher ist, ob der Schlüssel im Wörterbuch vorhanden ist, ihn aber in diesem Fall bereinigen möchte. Korrigiere mich, wenn ich falsch liege Amytis.
Hassan Baig
3

Wenn aus irgendeinem Grund der Löschschlüssel nicht funktioniert (als ob er bei mir nicht funktioniert hätte)

Sie können es herausspleißen und dann die undefinierten Werte filtern

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

Versuchen Sie nicht, sie zu verketten, da der Spleiß entfernte Elemente zurückgibt.

Leon
quelle
3

Wir können es auch als Funktion verwenden. Angular löst einen Fehler aus, wenn er als Prototyp verwendet wird. Danke @HarpyWar. Es hat mir geholfen, ein Problem zu lösen.

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");
Omkar Kamale
quelle
2

Es ist sehr einfach, wenn Sie die Abhängigkeit von underscore.js in Ihrem Projekt haben -

_.omit(myArray, "lastname")
vatsal
quelle
1

Mit dem "delete"Schlüsselwort wird das Array-Element in Javascript aus dem Array gelöscht.

Zum Beispiel,

Betrachten Sie die folgenden Aussagen.

var arrayElementToDelete = new Object();

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

delete arrayElementToDelete["status"];

In der letzten Zeile des Codes wird das Array-Element, dessen Schlüssel "Status" ist, aus dem Array entfernt.

Ravindra Miyani
quelle
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);

Ohne Schleifen / Iterationen erhalten wir das gleiche Ergebnis

Lalith Kumar
quelle
0

Für "Arrays":

Wenn Sie den Index kennen:

array.splice(index, 1);

Wenn Sie den Wert kennen:

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

Die am besten bewertete Antwort für deletefunktioniert gut bei Objekten, aber nicht für echte Arrays. Wenn ich es benutze delete, werden Elemente aus Schleifen entfernt, das Element bleibt jedoch unverändertempty und die Länge des Arrays ändert sich nicht. Dies kann in einigen Szenarien ein Problem sein.

Wenn ich zum Beispiel myArray.toString () auf myArray nach dem Entfernen über mache delete, wird ein leerer Eintrag erstellt, dh ,,

Arvind K.
quelle
0

Die einzige Arbeitsmethode für mich:

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

Verwendungszweck:

var new = removeItem( ["apple","banana", "orange"],  "apple");
// ---> ["banana", "orange"]
T.Todua
quelle
Warum nicht stattdessen Filter verwenden? Dies ist ein perfekter Anwendungsfall für Filter
Code Maniac