Короткий алфавитно-цифровой хэш Python с минимальными коллизиями

Процедура быстрого удаления дубликатов:

/* create temp table with one primary column id */
INSERT INTO temp(id) SELECT MIN(id) FROM list GROUP BY (isbn) HAVING COUNT(*)>1;
DELETE FROM list WHERE id IN (SELECT id FROM temp);
DELETE FROM temp;
23
задан ensnare 24 March 2010 в 19:14
поделиться

3 ответа

Почему бы вам просто не усечь SHA1 или MD5? У вас будет больше коллизий, если бы вы не усекали, но это все равно лучше, чем создавать свои собственные. Обратите внимание, что вы можете кодировать усеченный хэш с помощью base64, а не использовать шестнадцатеричный. Например.

import base64
import hashlib
hasher = hashlib.sha1("The quick brown fox")
base64.urlsafe_b64encode(hasher.digest()[:10])

Вы можете обрезать настолько мало (в том числе совсем не) или столько, сколько хотите, если вы понимаете компромиссы.

РЕДАКТИРОВАТЬ: поскольку вы упомянули безопасный URL-адрес, вы можете использовать urlsafe_b64encode и urlsafe_b64decode , который использует - и _ , а не + и / .

27
ответ дан 28 November 2019 в 06:50
поделиться

Самый маленький встроенный хэш, о котором я знаю, это md5

>>> import hashlib, base64
>>> d=hashlib.md5(b"hello worlds").digest(); d=base64.b64encode(d); 
>>> print(d)

b'S27ylES0wiLdFAGdUpFgCQ=='

Низкая коллизия и короткость в некоторой степени взаимоисключающие понятия из-за парадокса дня рождения

Чтобы сделать его urlsafe, нужно использовать функцию из модуля base64

>>> import base64
>>> base64.urlsafe_b64encode(hashlib.md5("hello world").digest())
'XrY7u-Ae7tCTyyK7j1rNww=='

Однако не должно быть проблем с хранением 16-байтового дайджеста md5 в базе данных в двоичной форме.

>>> md5bytes=hashlib.md5("hello world").digest()
>>> len(md5bytes)
16
>>> urllib.quote_plus(md5bytes)
'%5E%B6%3B%BB%E0%1E%EE%D0%93%CB%22%BB%8FZ%CD%C3'

Python 2

>>> base64.urlsafe_b64encode(md5bytes)
'XrY7u-Ae7tCTyyK7j1rNww=='

Python 3

>>> base64.urlsafe_b64encode(md5bytes).decode('ascii')
'XrY7u-Ae7tCTyyK7j1rNww=='

Вы можете выбрать quote_plus или urlsafe_b64encode для вашего url, а затем декодировать соответствующей функцией unquote_plus или urlsafe_b64decode, прежде чем искать их в базе данных.

24
ответ дан 28 November 2019 в 06:50
поделиться

Ниже представлено решение, в котором используются буквенно-цифровые символы плюс несколько знаков пунктуации. Он возвращает очень короткие строки (около 8 символов).

import binascii, struct

def myhash(s):
    return binascii.b2a_base64(struct.pack('i', hash(s)))
3
ответ дан 28 November 2019 в 06:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: