ES 6 Baru (Harmoni) memperkenalkan objek Set baru . Algoritma identitas yang digunakan oleh Set mirip dengan ===
operator sehingga tidak terlalu cocok untuk membandingkan objek:
var set = new Set();
set.add({a:1});
set.add({a:1});
console.log([...set.values()]); // Array [ Object, Object ]
Bagaimana cara menyesuaikan kesetaraan untuk objek Set untuk melakukan perbandingan objek yang mendalam? Apakah ada yang seperti Java equals(Object)
?
javascript
set
ecmascript-harmony
czerny
sumber
sumber
===
operator. Objek set ES6 tidak memiliki metode perbandingan apa pun. The.has()
Metode dan.add()
metode kerja hanya off itu menjadi objek yang sebenarnya sama atau nilai yang sama untuk primitif.Jawaban:
Set
Objek ES6 tidak memiliki metode perbandingan apa pun atau kustom membandingkan ekstensibilitas.Metode
.has()
,.add()
dan.delete()
metode hanya berfungsi sebagai objek aktual yang sama atau nilai yang sama untuk primitif dan tidak memiliki sarana untuk menyambungkan atau mengganti hanya logika itu.Anda mungkin bisa mendapatkan objek Anda sendiri dari a
Set
dan mengganti.has()
,.add()
dan.delete()
metode dengan sesuatu yang melakukan perbandingan objek dalam terlebih dahulu untuk menemukan apakah item tersebut sudah di Set, tetapi kinerjanya kemungkinan tidak akan baik karenaSet
objek yang mendasarinya tidak akan membantu sama sekali. Anda mungkin harus melakukan iterasi kasar melalui semua objek yang ada untuk menemukan kecocokan menggunakan perbandingan kustom Anda sendiri sebelum memanggil yang asli.add()
.Berikut beberapa info dari artikel ini dan diskusi tentang fitur ES6:
sumber
Set
atau tidak?Seperti yang disebutkan dalam jawaban jfriend00, kustomisasi relasi kesetaraan mungkin tidak mungkin .
Berikut kode hadiah garis besar komputasi yang efisien (tapi memori mahal) solusi :
Setiap elemen yang dimasukkan harus menerapkan
toIdString()
metode yang mengembalikan string. Dua objek dianggap sama jika dan hanya jikatoIdString
metode mereka mengembalikan nilai yang sama.sumber
item.toIdString()
invarian dan tidak dapat berubah. Karena jika bisa, makaGeneralSet
dapat dengan mudah menjadi tidak valid dengan item "duplikat" di dalamnya. Jadi, solusi seperti itu akan dibatasi hanya pada situasi tertentu di mana objek itu sendiri tidak berubah saat menggunakan set atau di mana set yang menjadi tidak valid tidak ada konsekuensinya. Semua masalah ini mungkin lebih jauh menjelaskan mengapa Perangkat ES6 tidak memaparkan fungsi ini karena hanya berfungsi dalam keadaan tertentu..delete()
untuk jawaban ini?Seperti yang dijawab oleh jawaban teratas , menyesuaikan kesetaraan merupakan masalah untuk objek yang dapat diubah. Berita baiknya adalah (dan saya terkejut belum ada yang menyebutkan ini) ada perpustakaan yang sangat populer yang disebut immutable-js yang menyediakan serangkaian tipe abadi yang memberikan semantik kesetaraan nilai mendalam yang Anda cari.
Inilah contoh Anda menggunakan immutable-js :
sumber
Untuk menambah jawaban di sini, saya melanjutkan dan mengimplementasikan pembungkus Peta yang menggunakan fungsi hash khusus, fungsi kesetaraan khusus, dan menyimpan nilai berbeda yang memiliki hash (kustom) setara dalam ember.
Bisa ditebak, ternyata lebih lambat daripada metode penggabungan string czerny .
Sumber lengkap di sini: https://github.com/makoConstruct/ValueMap
sumber
Point
definisi{ x: number, y: number }
maka Andaid string
mungkinx.toString() + ',' + y.toString()
.String
, maka Anda dapat melewati seluruh langkah hashing dan bucket seperti yang Anda katakan dan langsung saja menggunakanMap
atau bahkan objek biasa gaya lama dalam hal kunci yang diturunkan.{x: '1,2', y: '3'}
dan{x: '1', y: '2,3'}
, makaString(x) + ',' + String(y)
akan menampilkan nilai yang sama untuk kedua objek. Opsi yang lebih aman, dengan asumsi Anda dapat mengandalkanJSON.stringify()
deterministik, adalah mengambil keuntungan dari string yang keluar dan digunakanJSON.stringify([x, y])
sebagai gantinya.Membandingkannya secara langsung tampaknya tidak mungkin, tetapi JSON.stringify berfungsi jika kunci hanya diurutkan. Seperti yang saya tunjukkan dalam komentar
JSON.stringify ({a: 1, b: 2})! == JSON.stringify ({b: 2, a: 1});
Tetapi kita dapat mengatasinya dengan metode stringifikasi khusus. Pertama kita menulis metodenya
Stringify Kustom
Set
Sekarang kita menggunakan Set. Tapi kami menggunakan Set of Strings sebagai ganti objek
Dapatkan semua nilainya
Setelah kami membuat set dan menambahkan nilai, kami bisa mendapatkan semua nilai dengan
Berikut ini tautan dengan semua dalam satu file http://tpcg.io/FnJg2i
sumber
Mungkin Anda bisa mencoba menggunakan
JSON.stringify()
untuk melakukan perbandingan objek yang dalam.sebagai contoh :
sumber
Untuk pengguna naskah, jawaban oleh orang lain (terutama czerny ) dapat digeneralisasi ke kelas dasar yang aman dan dapat digunakan kembali:
Contoh penerapannya adalah ini sederhana: cukup timpa
stringifyKey
metode. Dalam kasus saya, saya merangkai beberapauri
properti.Contoh penggunaan kemudian seolah-olah ini biasa
Map<K, V>
.sumber
Buat set baru dari kombinasi kedua set, lalu bandingkan panjangnya.
set1 sama dengan set2 = true
set1 sama dengan set4 = false
sumber
Untuk seseorang yang menemukan pertanyaan ini di Google (seperti saya) yang ingin mendapatkan nilai Peta menggunakan objek sebagai Kunci:
Peringatan: jawaban ini tidak akan bekerja dengan semua objek
Keluaran:
sumber