Pada dasarnya, saya mencoba membuat objek objek unik, satu set. Saya memiliki ide cemerlang hanya menggunakan objek JavaScript dengan objek untuk nama properti. Seperti,
set[obj] = true;
Ini berfungsi, sampai batas tertentu. Ini berfungsi baik dengan string dan angka, tetapi dengan objek lain, mereka semua tampaknya "hash" dengan nilai yang sama dan mengakses properti yang sama. Apakah ada semacam cara saya bisa menghasilkan nilai hash unik untuk suatu objek? Bagaimana string dan angka melakukannya, dapatkah saya mengesampingkan perilaku yang sama?
javascript
hash
set
hashcode
Boog
sumber
sumber
JSON.stringify(obj)
atauobj.toSource()
dapat bekerja untuk Anda tergantung pada platform masalah dan target.toSource
jangan bekerja di Chrome btwJawaban:
Objek JavaScript hanya dapat menggunakan string sebagai kunci (apa pun yang dikonversi ke string).
Anda bisa, sebagai alternatif, mempertahankan array yang mengindeks objek yang dimaksud, dan menggunakan string indeks sebagai referensi ke objek. Sesuatu seperti ini:
Jelas itu sedikit bertele-tele, tetapi Anda bisa menulis beberapa metode yang menanganinya dan mendapatkan dan mengatur semua mau tak mau.
Edit:
Ini memunculkan poin menarik lainnya; Anda dapat mendefinisikan metode toString pada objek yang ingin Anda hash, dan yang dapat membentuk pengidentifikasi hash mereka.
sumber
Jika Anda ingin fungsi hashCode () seperti Java di JavaScript, itu milik Anda:
Itulah cara implementasi di Java (operator bitwise).
Harap perhatikan bahwa kode hash bisa positif dan negatif, dan itu normal, lihat HashCode memberikan nilai negatif . Jadi, Anda bisa mempertimbangkan untuk menggunakan
Math.abs()
fungsi ini.sumber
char
dicadangkan kata dalam JS dan dapat menyebabkan beberapa masalah. Beberapa nama lain akan lebih baik.pickOne["helloo".hashCode() % 20]
untuk arraypickOne
dengan 20 elemen. Saya dapatkanundefined
karena kode hash negatif, jadi ini adalah contoh di mana seseorang (saya) secara implisit mengasumsikan kode hash positif.Cara termudah untuk melakukan ini adalah memberikan masing-masing objek Anda
toString
metode unik sendiri :Saya memiliki masalah yang sama dan ini menyelesaikannya dengan sempurna bagi saya dengan kerepotan minimal, dan jauh lebih mudah untuk menerapkan kembali beberapa gaya Java yang berlemak
Hashtable
dan menambahkanequals()
danhashCode()
ke kelas objek Anda. Pastikan saja Anda tidak menempelkan string '<#MyObject: 12> ke hash Anda atau itu akan menghapus entri untuk objek Anda yang keluar dengan id itu.Sekarang semua hash saya benar-benar dingin. Saya juga baru saja memposting entri blog beberapa hari yang lalu tentang topik yang tepat ini .
sumber
equals()
danhashCode()
sehingga dua objek yang setara memiliki nilai hash yang sama. Menggunakan metode di atas berarti bahwa setiap instanceMyObject
akan memiliki string unik, yang berarti Anda harus menyimpan referensi ke objek tersebut untuk mendapatkan nilai yang benar dari peta. Memiliki kunci tidak ada artinya, karena tidak ada hubungannya dengan keunikan suatu objek.toString()
Fungsi yang berguna perlu diimplementasikan untuk jenis objek tertentu yang Anda gunakan sebagai kunci.toString
untuk secara langsung memetakan ke relasi ekivalensi sehingga dua objek membuat string yang sama jika mereka dianggap "sama".toString()
agar Anda dapat menggunakanObject
sebagai aSet
. Saya pikir saya salah memahami jawaban Anda sebagai mencoba memberikan solusi umum untuk menghindari penulisan yangtoString()
setaraequals()
atauhashCode()
berdasarkan kasus per kasus.Apa yang Anda jelaskan dicakup oleh Harmony WeakMaps , bagian dari spesifikasi ECMAScript 6 (versi JavaScript berikutnya). Yaitu: set di mana kunci dapat berupa apa saja (termasuk yang tidak ditentukan) dan tidak dapat dihitung.
Ini berarti tidak mungkin untuk mendapatkan referensi ke nilai kecuali Anda memiliki referensi langsung ke kunci (objek apa pun!) Yang tertaut ke sana. Ini penting untuk banyak alasan implementasi mesin yang berkaitan dengan efisiensi dan pengumpulan sampah, tetapi juga sangat keren karena memungkinkan semantik baru seperti izin akses yang dapat dibatalkan dan mengirimkan data tanpa mengekspos pengirim data.
Dari MDN :
WeakMaps tersedia di Firefox, Chrome, dan Edge saat ini. Mereka juga didukung di Node v7, dan di v6 dengan
--harmony-weak-maps
bendera.sumber
Map
?var m = new Map();m.set({},"abc"); console.log(m.get({}) //=>undefined
Ini hanya berfungsi jika Anda memiliki variabel yang sama dengan yang awalnya Anda rujuk dalam perintah yang ditetapkan. EGvar m = new Map();a={};m.set(a,"abc"); console.log(m.get(a) //=>undefined
Solusi yang saya pilih mirip dengan Daniel, tetapi daripada menggunakan objek pabrik dan menimpa toString, saya secara eksplisit menambahkan hash ke objek ketika pertama kali diminta melalui fungsi getHashCode. Sedikit berantakan, tapi lebih baik untuk kebutuhan saya :)
sumber
Object.defineProperty
denganenumerable
set kefalse
, sehingga Anda tidak akan crashfor .. in
loop.Untuk situasi spesifik saya, saya hanya peduli tentang kesetaraan objek sejauh kunci dan nilai-nilai primitif pergi. Solusi yang berhasil bagi saya adalah mengubah objek ke representasi JSON dan menggunakannya sebagai hash. Ada batasan seperti urutan definisi kunci yang berpotensi tidak konsisten; tapi seperti yang saya katakan itu bekerja untuk saya karena semua benda ini dihasilkan di satu tempat.
sumber
Saya mengumpulkan modul JavaScript kecil beberapa waktu lalu untuk menghasilkan kode hash untuk string, objek, array, dll. (Saya baru saja berkomitmen untuk GitHub :))
Pemakaian:
sumber
var hash1 = Hashcode.value({ a: 1, b: 2 }); var hash2 = Hashcode.value({ a: 2, b: 1 }); console.log(hash1, hash2);
akan log2867874173
2867874173
Spesifikasi JavaScript mendefinisikan akses properti yang diindeks sebagai melakukan konversi toString pada nama indeks. Sebagai contoh,
sama dengan
Ini diperlukan seperti dalam JavaScript
sama dengan
Dan ya, itu membuatku sedih juga :-(
sumber
Dalam ECMAScript 6 sekarang ada
Set
cara yang Anda inginkan: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SetIni sudah tersedia di Chrome, FF, dan IE11 terbaru.
sumber
Referensi: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
Anda dapat menggunakan simbol Es6 untuk membuat kunci unik dan mengakses objek. Setiap nilai simbol yang dikembalikan dari Symbol () unik. Nilai simbol dapat digunakan sebagai pengidentifikasi untuk properti objek; ini adalah satu-satunya tujuan tipe data.
sumber
Inilah solusi sederhana saya yang mengembalikan integer unik.
sumber
hashcode({a:1, b:2}) === hashcode({a:2, b:1})
dan banyak konflik lainnya.Berdasarkan pada judul, kita dapat menghasilkan hash yang kuat dengan js, dapat digunakan untuk menghasilkan hash unik dari suatu objek, array params, string, atau apa pun.
Kemudian untuk pengindeksan ini hindari kesalahan pencocokan yang memungkinkan, sambil memungkinkan untuk mengambil indeks dari params (hindari mencari / mengulang objek, dll.):
Output di atas di browser saya, itu harus sama untuk Anda juga ( Benarkah? ):
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string
sumber
Solusi saya memperkenalkan fungsi statis untuk
Object
objek global .Saya pikir ini lebih nyaman dengan fungsi memanipulasi objek lain dalam JavaScript
sumber
Saya akan mencoba sedikit lebih dalam daripada jawaban lainnya.
Walaupun JS memiliki dukungan hashing yang lebih baik, JS tidak akan secara ajaib melakukan hash semuanya dengan sempurna, dalam banyak kasus Anda harus mendefinisikan fungsi hash Anda sendiri. Misalnya Java memiliki dukungan hashing yang baik, tetapi Anda masih harus berpikir dan melakukan beberapa pekerjaan.
Satu masalah adalah dengan istilah hash / kode hash ... ada hashing kriptografi dan hashing non-kriptografi. Masalah lainnya, adalah Anda harus memahami mengapa hashing berguna dan cara kerjanya.
Ketika kita berbicara tentang hashing dalam JavaScript atau Java sebagian besar waktu kita berbicara tentang hashing non-kriptografi, biasanya tentang hashing untuk hashmap / hashtable (kecuali kita sedang mengerjakan otentikasi atau kata sandi, yang bisa Anda lakukan di sisi server menggunakan NodeJS. ..)
Itu tergantung pada data apa yang Anda miliki dan apa yang ingin Anda capai.
Data Anda memiliki keunikan "sederhana" yang alami:
Data Anda memiliki keunikan "komposit" alami:
Anda tidak tahu akan menjadi apa data Anda:
Tidak ada teknik hashing ajaib yang efisien untuk data yang tidak diketahui, dalam beberapa kasus itu cukup mudah, dalam kasus lain Anda mungkin harus berpikir dua kali. Jadi, bahkan jika JavaScript / ECMAScript menambahkan lebih banyak dukungan, tidak ada solusi bahasa ajaib untuk masalah ini.
Dalam latihan Anda membutuhkan dua hal: keunikan yang cukup, kecepatan yang cukup
Selain itu bagus untuk memiliki: "kode hash sama jika objek sama"
sumber
Jika Anda benar-benar ingin mengatur perilaku (saya menggunakan pengetahuan Java), maka Anda akan sulit sekali menemukan solusi dalam JavaScript. Sebagian besar pengembang akan merekomendasikan kunci unik untuk mewakili setiap objek, tetapi ini tidak seperti set, di mana Anda bisa mendapatkan dua objek yang identik masing-masing dengan kunci unik. Java API melakukan pekerjaan memeriksa nilai duplikat dengan membandingkan nilai kode hash, bukan kunci, dan karena tidak ada representasi nilai kode hash objek dalam JavaScript, menjadi hampir mustahil untuk melakukan hal yang sama. Bahkan perpustakaan Prototipe JS mengakui kekurangan ini, ketika dikatakan:
http://www.prototypejs.org/api/hash
sumber
Selain jawaban kelopak mata, berikut adalah fungsi yang mengembalikan ID unik yang dapat direproduksi untuk objek apa pun:
Seperti yang Anda lihat itu menggunakan daftar untuk pencarian yang sangat tidak efisien, namun itu yang terbaik yang bisa saya temukan untuk saat ini.
sumber
Jika Anda ingin menggunakan objek sebagai kunci, Anda harus menimpa Metode toString mereka, seperti yang telah disebutkan di sini. Fungsi hash yang digunakan semuanya baik-baik saja, tetapi mereka hanya bekerja untuk objek yang sama bukan untuk objek yang sama.
Saya telah menulis perpustakaan kecil yang membuat hash dari objek, yang dapat Anda gunakan dengan mudah untuk tujuan ini. Objek bahkan dapat memiliki urutan berbeda, hash akan sama. Secara internal Anda dapat menggunakan berbagai jenis untuk hash Anda (djb2, md5, sha1, sha256, sha512, ripemd160).
Berikut adalah contoh kecil dari dokumentasi:
Paket ini dapat digunakan di browser dan di Node-Js.
Repositori: https://bitbucket.org/tehrengruber/es-js-hash
sumber
Jika Anda ingin memiliki nilai unik dalam objek pencarian, Anda dapat melakukan sesuatu seperti ini:
Membuat objek pencarian
Menyiapkan fungsi kode hash
Obyek
Himpunan
Tipe yang lain
Hasil akhir
{ 1337: true, 01132337: true, StackOverflow: true }
Perhatikan bahwa
getHashCode
tidak mengembalikan nilai apa pun saat objek atau array kosongIni mirip dengan solusi @ijmacd
getHashCode
tetapi tidak memilikiJSON
ketergantungan.sumber
Saya menggabungkan jawaban dari kelopak mata dan KimKha.
Berikut ini adalah layanan angular dan mendukung angka, string, dan objek.
Contoh penggunaan:
Keluaran
Penjelasan
Seperti yang Anda lihat, inti dari layanan ini adalah fungsi hash yang dibuat oleh KimKha. Saya telah menambahkan tipe ke string sehingga struktur dari objek juga akan memengaruhi nilai hash akhir. Kunci hash untuk mencegah tumbukan array | objek benturan.
perbandingan objek kelopak mata digunakan untuk mencegah rekursi infinit dengan objek referensi diri.
Pemakaian
Saya membuat layanan ini sehingga saya bisa memiliki layanan kesalahan yang diakses dengan objek. Sehingga satu layanan dapat mendaftarkan kesalahan dengan objek yang diberikan dan yang lain dapat menentukan apakah ada kesalahan ditemukan.
yaitu
JsonValidation.js
UserOfData.js
Ini akan mengembalikan:
Sementara
Ini akan kembali
sumber
Cukup gunakan properti rahasia tersembunyi dengan
defineProperty
enumerable: false
Ini bekerja sangat cepat :
sumber