Javascript ES6 / ES5 im Array finden und ändern

133

Ich habe eine Reihe von Objekten. Ich möchte nach einem Feld suchen und es dann ändern:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundItem = items.find(x => x.id == item.id);
foundItem = item;

Ich möchte, dass das ursprüngliche Objekt geändert wird. Wie? (Es ist mir egal, ob es auch in lodash sein wird)

user3712353
quelle
Hat Ihr neueres Objekt itemeinen idSchlüssel? oder macht es Ihnen etwas aus, die ID sowie alle Eigenschaften des itemObjekts im Array-Eintrag zu haben?
Koushik Chatterjee

Antworten:

250

Mit findIndex können Sie den Index im Array des Objekts suchen und bei Bedarf ersetzen:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;

Dies setzt eindeutige IDs voraus. Wenn Ihre IDs doppelt vorhanden sind (wie in Ihrem Beispiel), ist es wahrscheinlich besser, wenn Sie forEach verwenden:

items.forEach((element, index) => {
    if(element.id === item.id) {
        items[index] = item;
    }
});
CodingIntrigue
quelle
16
@georg Das würde allerdings ein neues Array zurückgeben.
CodingIntrigue
3
Die Funktion => funktioniert in IE11 nicht. Kürzlich davon gebissen.
Lewis Cianci
1
Vielleicht wäre es besser, ein letSchlüsselwort anstelle vonvar
Inus Saha zu verwenden.
Nur zu Ihrer Information, dies funktioniert nicht in einigen Versionen von phantomJS
Sid
1
Ich bevorzuge die ausführlichere Methode, die @CodingIntrigue verwendet, anstatt den von map@georg verwendeten Einzeiler zu verwenden. Weniger mentale Gymnastik erforderlich, um herauszufinden, was los ist. Lohnt sich die zusätzliche Codezeile.
Joshua Pinter
43

Mein bester Ansatz ist:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

items[items.findIndex(el => el.id === item.id)] = item;

Referenz für findIndex

Und falls Sie nicht durch ein neues Objekt ersetzen möchten, sondern stattdessen die Felder von kopieren möchten item, können Sie Folgendes verwenden Object.assign:

Object.assign(items[items.findIndex(el => el.id === item.id)], item)

als Alternative mit .map():

Object.assign(items, items.map(el => el.id === item.id? item : el))

Funktionsansatz :

Ändern Sie das Array nicht, verwenden Sie ein neues, damit Sie keine Nebenwirkungen erzeugen

const updatedItems = items.map(el => el.id === item.id ? item : el)
Soldeplata Saketos
quelle
1
Bitte verlinken Sie auf eine englische Seite, wenn die ursprüngliche Frage auf Englisch war. In diesem Beispiel wird außerdem davon ausgegangen, dass das Objekt immer gefunden wird.
Raarts
1
Sie können es dann jederzeit in einen Try-Catch-Ausdruck einwickeln ... richtig?
Soldeplata Saketos
1
Und da er die Frage der Posts völlig wörtlich beantwortet, möchte er ein Element in einem Array bearbeiten. Er will nicht wissen, ob es existiert oder nicht, also nehmen wir an, dass er das schon vorher getan hat.
Soldeplata Saketos
@SoldeplataSaketos Ja, Sie könnten es in ein einwickeln, sollten es try/catchaber nicht, da es kein Ausnahmefall ist, das Element nicht zu finden. Dies ist ein Standardfall, den Sie berücksichtigen sollten, indem Sie den Rückgabewert von überprüfen findIndexund das Array erst dann aktualisieren, wenn das Element gefunden wurde.
Wayne
20

Ein anderer Ansatz ist die Verwendung von Spleiß .

Das splice()Verfahren ändert den Inhalt eines Felds durch Entfernen oder Ersetzen von vorhandenen Elementen und / oder das Hinzufügen neue Elemente an Ort und Stelle .

NB: Wenn Sie mit reaktiven Frameworks arbeiten, wird die "Ansicht" aktualisiert, und Ihr Array "weiß", dass Sie sie aktualisiert haben.

Antworten :

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

let foundIndex = items.findIndex(element => element.id === item.id)
items.splice(foundIndex, 1, item)

Und falls Sie nur einen Wert eines Elements ändern möchten, können Sie die Suchfunktion verwenden:

// Retrieve item and assign ref to updatedItem
let updatedItem = items.find((element) => { return element.id === item.id })

// Modify object property
updatedItem.aProp = ds.aProp
Toodoo
quelle
14

Bei einem geänderten Objekt und einem Array:

const item = {...}
let items = [{id:2}, {id:3}, {id:4}];

Aktualisieren Sie das Array mit dem neuen Objekt, indem Sie über das Array iterieren:

items = items.map(x => (x.id === item.id) ? item : x)
Fremder
quelle
Bitte fügen Sie nicht nur Code ein. Erklären Sie, was getan wird und wie dies das Problem löst.
Spencer
1
Ich denke, dies ist die beste Lösung, da es die beste Leistung hat, da es nur einmal über das Array geht und auch die Referenz des Arrays ändert, so dass veränderbare Situationen vermieden werden
Ohad Sadan
6

Kann Gebrauch sein Filter .

const list = [{id:0}, {id:1}, {id:2}];
let listCopy = [...list];
let filteredDataSource = listCopy.filter((item) => {
       if (item.id === 1) {
           item.id = 12345;
        }

        return item;
    });
console.log(filteredDataSource);

Array [Objekt {ID: 0}, Objekt {ID: 12345}, Objekt {ID: 2}]

Katwal-Dipak
quelle
Ich mag Filter, weil es erlaubt, ein neues Array zu erstellen und dafür auch nicht vorhandene Einträge 'gelöscht' werden
pungggi
0

arbeitete für mich

let returnPayments = [ ...this.payments ];

returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;
Daniel Laera
quelle
1
Bitte fügen Sie nicht nur Code ein. Erklären Sie, was getan wird und wie dies das Problem löst.
Adrian Mole
Die akzeptierte, am besten bewertete Antwort ist nicht viel anders, aber Sie haben nicht darauf hingewiesen, dass sie ihre Antwort aktualisieren. Warum ist das so?
li x
0

Während die meisten der vorhandenen Antworten großartig sind, möchte ich eine Antwort mit einer traditionellen for-Schleife einfügen, die auch hier berücksichtigt werden sollte. Das OP fordert eine Antwort an, die ES5 / ES6-kompatibel ist, und es gilt die traditionelle for-Schleife :)

Das Problem bei der Verwendung von Array-Funktionen in diesem Szenario besteht darin, dass sie keine Objekte mutieren. In diesem Fall ist jedoch eine Mutation erforderlich. Der Leistungsgewinn bei der Verwendung einer herkömmlichen for-Schleife ist nur ein (großer) Bonus.

const findThis = 2;
const items = [{id:1, ...}, {id:2, ...}, {id:3, ...}];

for (let i = 0, l = items.length; i < l; ++i) {
  if (items[i].id === findThis) {
    items[i].iAmChanged = true;
    break;
  }
}

Obwohl ich ein großer Fan von Array-Funktionen bin, lassen Sie sie nicht das einzige Werkzeug in Ihrer Toolbox sein. Wenn der Zweck darin besteht, das Array zu mutieren, passen sie nicht am besten.

Jørgen
quelle
0

Einzeiler mit Spread Operator.

 const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));
tonymayoral
quelle