Javascript ES6 / ES5 temukan dalam array dan ubah

133

Saya memiliki berbagai objek. Saya ingin mencari berdasarkan beberapa bidang, dan kemudian mengubahnya:

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

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

Saya ingin mengubah objek asli. Bagaimana? (Saya tidak peduli apakah itu akan di lodash juga)

pengguna3712353
sumber
Dosis objek baru Anda itemberisi idkunci? atau apakah Anda keberatan memiliki id serta semua properti dari itemobjek dalam entri array?
Koushik Chatterjee

Jawaban:

251

Anda dapat menggunakan findIndex untuk menemukan indeks dalam array objek dan menggantinya sesuai kebutuhan:

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

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

Ini mengasumsikan ID unik. Jika ID Anda digandakan (seperti dalam contoh Anda), mungkin lebih baik jika Anda menggunakan forEach:

items.forEach((element, index) => {
    if(element.id === item.id) {
        items[index] = item;
    }
});
CodingIntrigue
sumber
16
@georg Itu akan mengembalikan array baru.
CodingIntrigue
3
Fungsi => tidak akan berfungsi di IE11. Baru-baru ini digigit oleh ini.
Lewis Cianci
1
mungkin akan lebih baik menggunakan letkata kunci daripadavar
Inus Saha
Hanya FYI, ini tidak berfungsi di beberapa versi phantomJS
Sid
1
Saya lebih suka metode yang lebih verbose menggunakan @CodingIntrigue daripada menggunakan satu-liner mapyang menggunakan @georg. Senam mental yang lebih sedikit diperlukan untuk mengetahui apa yang terjadi. Layak dengan baris kode tambahan.
Joshua Pinter
44

Pendekatan terbaik saya adalah:

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

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

Referensi untuk findIndex

Dan jika Anda tidak ingin mengganti dengan objek baru, tetapi alih-alih menyalin bidang item, Anda dapat menggunakan Object.assign:

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

sebagai alternatif dengan .map():

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

Pendekatan fungsional :

Jangan memodifikasi array, gunakan yang baru, jadi Anda tidak menghasilkan efek samping

const updatedItems = items.map(el => el.id === item.id ? item : el)
Saketos Soldeplata
sumber
1
Harap tautkan ke halaman bahasa Inggris jika pertanyaan aslinya dalam bahasa Inggris. Juga, contoh ini mengasumsikan objek selalu ditemukan.
raarts
1
Anda selalu dapat membungkusnya dalam ekspresi coba tangkap lalu ... kan?
Soldeplata Saketos
1
Dan sepenuhnya harfiah untuk pertanyaan posting, ia ingin mengedit elemen dalam array. Dia tidak ingin tahu apakah itu ada atau tidak, jadi kita asumsikan dia sudah melakukan itu sebelumnya.
Soldeplata Saketos
@SoldeplataSaketos ya, Anda bisa membungkusnya dalam try/catch, tetapi Anda tidak boleh, karena tidak menemukan elemen bukanlah kasus luar biasa; ini merupakan kasus standar yang harus Anda pertanggungjawabkan dengan memeriksa nilai balik findIndexdan kemudian hanya memperbarui array ketika elemen ditemukan.
Wayne
20

Pendekatan lain adalah dengan menggunakan sambungan .

The splice()Metode mengubah isi array dengan menghapus atau mengganti elemen yang ada dan / atau menambahkan elemen baru di tempat .

NB: Jika Anda bekerja dengan kerangka kerja reaktif, itu akan memperbarui "view", array Anda "mengetahui" Anda telah memperbaruinya.

Jawaban:

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

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

Dan jika Anda hanya ingin mengubah nilai suatu item, Anda dapat menggunakan fungsi find :

// 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
sumber
14

Diberikan objek dan array yang diubah:

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

Perbarui array dengan objek baru dengan mengulangi array:

items = items.map(x => (x.id === item.id) ? item : x)
Sesama Asing
sumber
Tolong jangan hanya menempelkan kode. Jelaskan apa yang sedang dilakukan dan bagaimana ini memecahkan masalah.
Spencer
1
Saya pikir ini adalah solusi terbaik karena ini memiliki kinerja terbaik karena hanya pergi ke array sekali saja dan juga mengubah referensi array, sehingga akan menghindari situasi yang bisa berubah
Ohad Sadan
6

Mungkin menggunakan 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 [Objek {id: 0}, Objek {id: 12345}, Obyek {id: 2}]

katwal-Dipak
sumber
Saya suka filter karena memungkinkan untuk membuat array baru dan untuk ini juga tidak ada entri yang 'dihapus'
pungggi
0

bekerja untukku

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

returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;
Daniel Laera
sumber
1
Tolong jangan hanya menempelkan kode. Jelaskan apa yang sedang dilakukan dan bagaimana ini memecahkan masalah.
Adrian Mole
Jawaban yang paling banyak diterima tidak jauh berbeda, namun Anda tidak menunjuk mereka memperbarui di sana .. mengapa begitu?
li x
0

Meskipun sebagian besar jawaban yang ada bagus, saya ingin memasukkan jawaban menggunakan tradisional untuk loop, yang juga harus dipertimbangkan di sini. OP meminta jawaban yang kompatibel dengan ES5 / ES6, dan tradisional untuk loop berlaku :)

Masalah dengan menggunakan fungsi array dalam skenario ini, adalah bahwa mereka tidak bermutasi objek, tetapi dalam kasus ini, mutasi adalah persyaratan. Keuntungan kinerja menggunakan loop tradisional untuk hanya bonus (besar).

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

Meskipun saya penggemar berat fungsi array, jangan biarkan mereka menjadi satu-satunya alat di kotak alat Anda. Jika tujuannya bermutasi array, mereka bukan yang paling cocok.

Jørgen
sumber
0

Satu-liner menggunakan operator spread.

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