Jumlah digit yang terbatas akan mengakibatkan tabrakan untuk sejumlah besar item hash, itulah mengapa Anda tidak boleh memperlakukannya sebagai kunci unik - ini cenderung berubah menjadi masalah ulang tahun.
Alex North-Keys
1
Saya telah memilih "CityHash" untuk mem-hash string menjadi 19 digit integer panjang (64bit integers), berharap ini akan menyebabkan potensi tabrakan yang lebih sedikit daripada saran Raymond di bawah ini. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame
Jawaban:
157
Ya, Anda dapat menggunakan modul hashlib built-in atau fungsi hash built-in . Kemudian, potong delapan digit terakhir menggunakan operasi modulo atau operasi pemotongan string pada bentuk integer dari hash:
>>> s ='she sells sea shells by the sea shore'>>># Use hashlib>>>import hashlib
>>> int(hashlib.sha1(s).hexdigest(),16)%(10**8)58097614L>>># Use hash()>>> abs(hash(s))%(10**8)82148974
pengumuman layanan publik ... teknik ini sebenarnya tidak menghasilkan nilai hash unik untuk string; itu menghitung hash dan kemudian memungut menjadi nilai unik yang tidak dijamin
twneale
89
pengumuman layanan publik ... kecuali untuk kasus khusus dari hash sempurna atas kumpulan nilai input yang terbatas, fungsi hash tidak seharusnya menghasilkan nilai unik yang dijamin.
Raymond Hettinger
5
Apakah Anda membaca pertanyaan OP? Dia (atau dia) ingin (atau membutuhkan) 8 tempat desimal. Juga, cara kerja tabel hash adalah dengan melakukan hash ke dalam ruang pencarian kecil (tabel jarang). Anda sepertinya tidak tahu fungsi hash yang diinginkan biasanya digunakan untuk dan tidak peduli dengan pertanyaan sebenarnya yang ditanyakan.
Raymond Hettinger
17
Saya membaca pertanyaannya. Saya hanya mengamati bahwa pada ruang input yang sama dengan SHA-1, jawaban Anda secara astronomis lebih mungkin menghasilkan tabrakan daripada tidak. Setidaknya beberapa derajat keunikan secara implisit diperlukan oleh pertanyaan, tetapi jawaban Anda adalah fungsi hash dengan semangat yang sama seperti yang hanya mengembalikan 12345678 untuk setiap masukan. Saya dapat secara eksperimental menghasilkan tabrakan dengan sedikitnya 1000 input menggunakan metode ini. Untuk mempertahankan probabilitas tabrakan yang sama seperti SHA-1, Anda harus memetakan SHA-1 yang tidak terpotong ke bilangan bulat 8 digit. Saya pikir itu layak untuk PSA
twneale
20
Hati-hati, hash tidak dijamin untuk memberikan hasil yang sama di seluruh platform dan berjalan.
Tn. Napik
95
Jawaban Raymond sangat bagus untuk python2 (meskipun, Anda tidak memerlukan abs () atau parens sekitar 10 ** 8). Namun, untuk python3, ada peringatan penting. Pertama, Anda harus memastikan bahwa Anda meneruskan string yang dienkode. Hari-hari ini, dalam banyak situasi, mungkin juga lebih baik untuk menghindar dari sha-1 dan menggunakan sesuatu seperti sha-256. Jadi, pendekatan hashlib adalah:
>>>import hashlib
>>> s ='your string'>>> int(hashlib.sha256(s.encode('utf-8')).hexdigest(),16)%10**880262417
Jika Anda ingin menggunakan fungsi hash (), peringatan pentingnya adalah, tidak seperti di Python 2.x, di Python 3.x, hasil hash () hanya akan konsisten dalam suatu proses, bukan di seluruh pemanggilan python. Lihat disini:
Jadi, tergantung pada apakah ini penting dalam aplikasi Anda (itu terjadi di aplikasi saya), Anda mungkin ingin tetap menggunakan pendekatan berbasis hashlib.
Perlu dicatat bahwa jawaban ini memiliki peringatan yang sangat penting karena Python 3.3, untuk melindungi dari tar-pitting Python 3.3 dan yang lebih tinggi gunakan hash seed acak saat startup.
Wolph
Jika angka bukan persyaratan utama Anda, Anda juga bisa menggunakan hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]penyihir yang masih akan bertabrakan
lony
Mereka harus menaruhnya di kotak!
Tomasz
3
Sekadar melengkapi jawaban JJC, di python 3.5.3 perilakunya sudah benar jika menggunakan hashlib seperti ini:
Saya membagikan implementasi nodejs kami dari solusi seperti yang diterapkan oleh @Raymond Hettinger.
var crypto = require('crypto');
var s ='she sells sea shells by the sea shore';
console.log(BigInt('0x'+ crypto.createHash('sha1').update(s).digest('hex'))%(10n**8n));
Anda berbagi solusi nodejs dalam pertanyaan tentang python?
Harabeck
Ya, saat kita membangun sistem - backend memproses ini menggunakan python sedangkan frontend menggunakan node.js. Diperlukan untuk memastikan keduanya bekerja dengan lancar.
Jawaban:
Ya, Anda dapat menggunakan modul hashlib built-in atau fungsi hash built-in . Kemudian, potong delapan digit terakhir menggunakan operasi modulo atau operasi pemotongan string pada bentuk integer dari hash:
sumber
Jawaban Raymond sangat bagus untuk python2 (meskipun, Anda tidak memerlukan abs () atau parens sekitar 10 ** 8). Namun, untuk python3, ada peringatan penting. Pertama, Anda harus memastikan bahwa Anda meneruskan string yang dienkode. Hari-hari ini, dalam banyak situasi, mungkin juga lebih baik untuk menghindar dari sha-1 dan menggunakan sesuatu seperti sha-256. Jadi, pendekatan hashlib adalah:
Jika Anda ingin menggunakan fungsi hash (), peringatan pentingnya adalah, tidak seperti di Python 2.x, di Python 3.x, hasil hash () hanya akan konsisten dalam suatu proses, bukan di seluruh pemanggilan python. Lihat disini:
Ini berarti solusi berbasis hash () disarankan, yang dapat disingkat menjadi hanya:
hash(s) % 10**8
hanya akan mengembalikan nilai yang sama dalam menjalankan skrip tertentu:
Jadi, tergantung pada apakah ini penting dalam aplikasi Anda (itu terjadi di aplikasi saya), Anda mungkin ingin tetap menggunakan pendekatan berbasis hashlib.
sumber
hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]
penyihir yang masih akan bertabrakanSekadar melengkapi jawaban JJC, di python 3.5.3 perilakunya sudah benar jika menggunakan hashlib seperti ini:
sumber
Saya membagikan implementasi nodejs kami dari solusi seperti yang diterapkan oleh @Raymond Hettinger.
sumber