Entfernen Sie Objekte aus dem Array nach Objekteigenschaft

136
var listToDelete = ['abc', 'efg'];

var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

Wie entferne ich ein Objekt aus dem Array, indem ich die Objekteigenschaft abgleichen kann?

Bitte nur natives JavaScript.

Ich habe Probleme mit der Verwendung von Spleiß, da die Länge mit jedem Löschen abnimmt. Wenn Sie Klon verwenden und den Originalindex spleißen, besteht immer noch das Problem, dass die Länge abnimmt.

Dan Kanze
quelle
1
Rückwärtsschleifen sollte das Problem der Längenänderung beheben
Ian
1
Es ist so schade, dass es keinen Standard gibt, um Elemente aus einem Objektarray zu entfernen. Kein Wunder, dass es so viele Skripte von Drittanbietern gibt. Es ist eine grundlegende Sache.
Gitarrenglas

Antworten:

155

Ich nehme an, Sie haben so spliceetwas benutzt?

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

Alles, was Sie tun müssen, um den Fehler zu beheben, ist eine Dekrementierung ifür das nächste Mal (und eine Rückwärtsschleife ist ebenfalls eine Option):

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
        i--;
    }
}

Um zeitlineare Löschungen zu vermeiden, können Sie Array-Elemente schreiben, die Sie über das Array behalten möchten :

var end = 0;

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) === -1) {
        arrayOfObjects[end++] = obj;
    }
}

arrayOfObjects.length = end;

Um zeitlich lineare Suchvorgänge in einer modernen Laufzeit zu vermeiden, können Sie ein Hash-Set verwenden:

const setToDelete = new Set(listToDelete);
let end = 0;

for (let i = 0; i < arrayOfObjects.length; i++) {
    const obj = arrayOfObjects[i];

    if (setToDelete.has(obj.id)) {
        arrayOfObjects[end++] = obj;
    }
}

arrayOfObjects.length = end;

was in eine schöne Funktion eingepackt werden kann:

const filterInPlace = (array, predicate) => {
    let end = 0;

    for (let i = 0; i < array.length; i++) {
        const obj = array[i];

        if (predicate(obj)) {
            array[end++] = obj;
        }
    }

    array.length = end;
};

const toDelete = new Set(['abc', 'efg']);

const arrayOfObjects = [{id: 'abc', name: 'oh'},
                        {id: 'efg', name: 'em'},
                        {id: 'hij', name: 'ge'}];

filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id));
console.log(arrayOfObjects);

Wenn Sie es nicht an Ort und Stelle tun müssen, ist das Array#filter:

const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));
Ry-
quelle
79

Sie können ein Element anhand einer seiner Eigenschaften entfernen, ohne die folgenden Bibliotheken von Drittanbietern zu verwenden:

var removeIndex = array.map(item => item.id)
                       .indexOf("abc");

~removeIndex && array.splice(removeIndex, 1);
Parlament
quelle
1
Dies ist eine wirklich elegante Antwort.
Scott Silvi
Eine andere Sache, die ich möchte, gibt es separate Schaltflächen für jedes Objekt im Array. Wenn ich dieses bestimmte Objekt im Array löschen möchte, klicke ich auf die Schaltfläche und das sollte in ein anderes sekundäres Array verschoben werden. wie es geht . Ich habe Winkel js ng-repeat verwendet, um Elemente zu generieren.
Kannst
sehr schöne und elegante Herangehensweise. ein dickes Lob! Nur eine Sache zur Vorsicht; Wenn der erforderliche Index nicht im Kartenarray gefunden wird, wird -1 zurückgegeben. Somit entfernt der Spleiß das letzte Element.
mcy
14
Oder wenn Sie durch die Tilde in der letzten Zeile verwirrt werden, wird dies möglicherweise klarer: (removeIndex> = 0) && array.splice (removeIndex, 1);
Wojjas
1
@parliament - Gibt es in Ihrem Beispiel eine Dokumentation zur Tilde? Ich habe das noch nie gesehen.
webdad3
43

Mit lodash / Unterstrich:

Wenn Sie das vorhandene Array selbst ändern möchten, müssen Sie Spleiß verwenden . Hier ist der etwas bessere / lesbarere Weg mit findWhere von Unterstrich / lodash:

var items= [{id:'abc',name:'oh'}, // delete me
                  {id:'efg',name:'em'},
                  {id:'hij',name:'ge'}];

items.splice(_.indexOf(items, _.findWhere(items, { id : "abc"})), 1);

Mit ES5 oder höher

( ohne lodash / Unterstrich )

Ab ES5 haben wir eine findIndexArray-Methode, die ohne Lodash / Unterstrich einfach ist

items.splice(items.findIndex(function(i){
    return i.id === "abc";
}), 1);

(ES5 wird in fast allen Morden-Browsern unterstützt)

Über Find und seine Browser - Kompatibilität

Rahul R.
quelle
Wie entferne ich alle Elemente in einem Array von Objekten, aber ich brauche auch den Rückruf
Muhaimin
Was meinst du auch mit Rückruf? Du kannst den obigen Code verwenden, um das Objekt aus dem Array zu entfernen.
Rahul R.
1
Schön. Ich werde dies zu meinem Werkzeuggürtel hinzufügen
abyrne85
Eine andere Sache, die ich möchte, gibt es separate Schaltflächen für jedes Objekt im Array. Wenn ich dieses bestimmte Objekt im Array löschen möchte, klicke ich auf die Schaltfläche und das sollte in ein anderes sekundäres Array verschoben werden. wie es geht . Ich habe Winkel js ng-repeat verwendet, um Elemente zu generieren.
Kannst
1
Ich liebe diesen ES5-Vorschlag, da er sogar kürzer geschrieben werden kannitems.splice(items.findIndex(i => i.id === "abc"), 1)
bramchi
27

findIndex funktioniert für moderne Browser:

var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = arr.findIndex(function(o){
     return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);
fatlinesofcode
quelle
Ich mag diese moderne Antwort, außer dass Ihr Code den Fall nicht
erfasst,
2
sehr einfache Antwort im Vergleich zu anderen und funktioniert gut.
Arun
einfache, aber mächtige Antwort
Shelly
15

So löschen Sie ein Objekt anhand seiner ID in einem bestimmten Array;

const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);
Naresh Chennuri
quelle
10

Wenn Sie es nur aus dem vorhandenen Array entfernen und kein neues erstellen möchten, versuchen Sie Folgendes:

var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);
user2704940
quelle
7
Beachten Sie, dass diese Antwort erfordert die Strich Bibliothek
JoshuaDavid
2
Ich würde dies nicht empfehlen, denn wenn das Element nicht gefunden wird, gibt _.indexOf -1 => items.splice (-1,1) zurück
user1441287
6

Schleife in umgekehrter Reihenfolge durch Dekrementieren i, um das Problem zu vermeiden:

for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

Oder verwenden Sie filter:

var newArray = arrayOfObjects.filter(function(obj) {
    return listToDelete.indexOf(obj.id) === -1;
});
Felix Rabe
quelle
5

Überprüfen Sie dies mit Set- und ES6-Filter.

  let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
  console.log(result);

Hier ist JsFiddle: https://jsfiddle.net/jsq0a0p1/1/

Miroslav Savovski
quelle
1
Funktioniert perfekt!
Antoni Kepinski
Meiner Ansicht nach modernster und elegantester Ansatz.
AC Patrice
4

Bitte nur natives JavaScript.

Als alternative, "funktionalere" Lösung, die an ECMAScript 5 arbeitet, können Sie Folgendes verwenden:

var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}]; // all that should remain

arrayOfObjects.reduceRight(function(acc, obj, idx) {
    if (listToDelete.indexOf(obj.id) > -1)
        arrayOfObjects.splice(idx,1);
}, 0); // initial value set to avoid issues with the first item and
       // when the array is empty.

console.log(arrayOfObjects);
[ { id: 'hij', name: 'ge' } ]

Gemäß der Definition von 'Array.prototype.reduceRight' in ECMA-262 :

reduRight ändert das Objekt, für das es aufgerufen wird , nicht direkt, aber das Objekt kann durch die Aufrufe von callbackfn mutiert werden .

Dies ist also eine gültige Verwendung von reduceRight.

Sylvain Leroux
quelle
2
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

gemäß Ihrer Antwort wird so sein. Wenn Sie auf ein bestimmtes Objekt klicken, senden Sie den Index im Parameter für die Funktion "Löschen". Dieser einfache Code funktioniert wie ein Zauber.

function deleteme(i){
    if (i > -1) {
      arrayOfObjects.splice(i, 1);
    }
}
Subhojit Mondal
quelle
1
Thnaks das hat viel geholfen :)
RAJESH KUMAR ARUMUGAM
1

mit filter & indexOf

withLodash = _.filter(arrayOfObjects, (obj) => (listToDelete.indexOf(obj.id) === -1));
withoutLodash = arrayOfObjects.filter(obj => listToDelete.indexOf(obj.id) === -1);

mit Filter & enthält

withLodash = _.filter(arrayOfObjects, (obj) => (!listToDelete.includes(obj.id)))
withoutLodash = arrayOfObjects.filter(obj => !listToDelete.includes(obj.id));
user3437231
quelle
0

Wenn Sie kurze und selbstbeschreibende Parameter mögen oder wenn Sie keinen spliceeinfachen Filter verwenden möchten oder wenn Sie einfach eine SQL-Person wie ich sind:

function removeFromArrayOfHash(p_array_of_hash, p_key, p_value_to_remove){
    return p_array_of_hash.filter((l_cur_row) => {return l_cur_row[p_key] != p_value_to_remove});
}

Und ein Beispiel für die Verwendung:

l_test_arr = 
[
    {
         post_id: 1,
        post_content: "Hey I am the first hash with id 1"
    },
    {
        post_id: 2,
        post_content: "This is item 2"
    },
    {
        post_id: 1,
        post_content: "And I am the second hash with id 1"
    },
    {
        post_id: 3,
        post_content: "This is item 3"
    },
 ];



 l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 2); // gives both of the post_id 1 hashes and the post_id 3
 l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 1); // gives only post_id 3 (since 1 was removed in previous line)
Mehmet Kaplan
quelle
-1

Sie können verwenden filter. Diese Methode gibt das Element immer zurück, wenn die Bedingung erfüllt ist. Wenn Sie also nach ID entfernen möchten, müssen Sie alle Elemente behalten, die nicht mit der angegebenen ID übereinstimmen. Hier ist ein Beispiel:

arrayOfObjects = arrayOfObjects.filter (obj => obj.id! = idToRemove)

David Benitez Riba
quelle