Javascript ES6 / ES5 dizide bul ve değiştir


133

Bir dizi nesnem var. Bir alana göre bulmak ve sonra değiştirmek istiyorum:

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

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

Orijinal nesneyi değiştirmesini istiyorum. Nasıl? (Lodash'ta olup olmayacağı da umurumda değil)


Yeni nesneniz itembir idanahtar içeriyor mu? veya itemdizi girişinde nesnenin tüm özelliklerinin yanı sıra id'nin de olmasını ister misiniz ?
— Koushik Chatterjee

Yanıtlar:


252

Dizini nesne dizisinde bulmak ve gerektiği gibi değiştirmek için findIndex'i kullanabilirsiniz :

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

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

Bu, benzersiz kimlikler olduğunu varsayar. Kimlikleriniz yineleniyorsa (örneğinizde olduğu gibi), muhtemelen forEach'i kullanmanız daha iyidir:

items.forEach((element, index) => {
    if(element.id === item.id) {
        items[index] = item;
    }
});

16
@georg Bu yine de yeni bir dizi döndürecektir.
— CodingIntrigue

3
=> İşlevi IE11'de çalışmaz. Son zamanlarda bununla ısırıldı.
— Lewis Cianci

1
letyerine anahtar kelime kullanmak daha iyi olabilirvar
— Inus Saha

Bilginize, bu phantomJS'nin bazı sürümlerinde çalışmıyor
— Sid

1
@Georg'un kullandığı tek satırlık yöntemi kullanmak yerine @CodingIntrigue'nun kullandığı daha ayrıntılı yöntemi tercih ediyorum map. Neler olduğunu anlamak için daha az zihinsel jimnastik gerekli. Ekstra kod satırına değer.
— Joshua Pinter

44

En iyi yaklaşımım:

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

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

FindIndex için referans

Yeni nesneyle değiştirmek istemiyorsanız, bunun yerine alanlarını kopyalamak itemistiyorsanız, şunu kullanabilirsiniz Object.assign:

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

şununla alternatif olarak .map():

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

Fonksiyonel yaklaşım :

Diziyi değiştirmeyin, yeni bir tane kullanın, böylece yan etkiler oluşturmazsınız

const updatedItems = items.map(el => el.id === item.id ? item : el)

1
Asıl soru İngilizce ise lütfen İngilizce bir sayfaya bağlantı verin. Ayrıca, bu örnek nesnenin her zaman bulunduğunu varsayar.
— 2017

1
Her zaman bir deneme yakalama ifadesine sarabilirsiniz o zaman ... değil mi?
— Soldeplata Saketos

1
Ve gönderilerin sorusuna tamamen gerçek olduğundan, bir dizideki bir öğeyi düzenlemek istiyor. Var olup olmadığını bilmek istemiyor, bu yüzden bunu daha önce yaptığını varsayıyoruz.
— Soldeplata Saketos

Evet @SoldeplataSaketos, sen verebilir bir alanına kaydırmak try/catchelemanı görmediklerine istisnai bir durum değildir çünkü, ama sen olmamalı; bu, dönüş değerini kontrol ederek findIndexve ardından yalnızca öğe bulunduğunda diziyi güncelleyerek hesaba katmanız gereken standart bir durumdur .
— Wayne

20

Diğer bir yaklaşım, splice kullanmaktır .

splice()Yöntem, çıkarma veya varolan öğeleri değiştirerek ve / veya yeni elemanları eklenerek bir dizi içeriğini değiştirir yerine .

Not: Reaktif çerçevelerle çalışıyorsanız, "görünümü", yani onu güncellediğinizi "bilerek" dizinizi güncelleyecektir.

Cevap :

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

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

Ve bir öğenin yalnızca bir değerini değiştirmek istiyorsanız, bul işlevini kullanabilirsiniz :

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

// Modify object property
updatedItem.aProp = ds.aProp

15

Değişen bir nesne ve bir dizi verildiğinde:

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

Dizi üzerinde yineleyerek diziyi yeni nesneyle güncelleyin:

items = items.map(x => (x.id === item.id) ? item : x)

Lütfen kodu yapıştırmayın. Ne yapıldığını ve bunun sorunu nasıl çözdüğünü açıklayın.
— Spencer

1
Bunun en iyi çözüm olduğunu düşünüyorum çünkü diziyi yalnızca bir kez gözden geçiriyor ve dizinin referansını değiştiriyor, böylece değişken durumlardan kaçınacak
— Ohad Sadan

6

Kullanım olabilir Filtre .

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

Dizi [Nesne {id: 0}, Nesne {id: 12345}, Nesne {id: 2}]


Filtreyi seviyorum çünkü yeni bir dizi oluşturmaya izin veriyor ve bunun için de mevcut olmayan girişler 'siliniyor'
— pungggi

0

benim için çalıştı

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

returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;

1
Lütfen kodu yapıştırmayın. Ne yapıldığını ve bunun sorunu nasıl çözdüğünü açıklayın.
— Adrian Mole

Kabul edilen en çok oylanan cevap pek farklı değil, ancak cevaplarını orada güncelleyerek onlara işaret etmediniz .. Neden bu?
— li x

0

Mevcut yanıtların çoğu harika olsa da, burada da dikkate alınması gereken geleneksel bir for döngüsü kullanan bir yanıt eklemek istiyorum. OP, ES5 / ES6 uyumlu bir yanıt ister ve geleneksel for döngüsü geçerlidir :)

Bu senaryoda dizi işlevlerini kullanmanın sorunu, nesneleri değiştirmemeleridir, ancak bu durumda mutasyon bir gerekliliktir. Geleneksel bir for döngüsü kullanmanın performans kazancı sadece (çok büyük) bir 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;
  }
}

Dizi işlevlerinin büyük bir hayranı olsam da, bunların alet kutunuzdaki tek araç olmasına izin vermeyin. Amaç diziyi değiştirmekse, bunlar en uygun olanlar değildir.


0

Yayılma operatörünü kullanan tek astar.

 const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.