UUID Python представлен в виде специальных символов
-
21-09-2019 - |
Вопрос
При создании UUID в Python выполните следующие действия:
>>> uuid.uuid1()
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
Как можно преобразовать этот UUID в строку, состоящую из заглавных букв алфавита A-Z минус символы D, F, I, O, Q и U, плюс числовые цифры, плюс символы «+» и «=".то естьиз целого числа или строки в набор из 32 символов (относительно удобных для распознавания текста):
[ABCEGHJKLMNPRSTVWXYZ1234567890+=]
Я назову это OCRf
set (для распознавания текста).
Я хотел бы иметь изоморфную функцию:
def uuid_to_ocr_friendly_chars(uid)
"""takes uid, an integer, and transposes it into a string made
of the the OCRf set
"""
...
Моя первая мысль — пройти процесс изменения uuid на base 32.например
OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="
def uuid_to_ocr_friendly_chars(uid):
ocfstr = ''
while uid > 1:
ocfstr += OCRf[uid % 32]
uid /= 32
return ocfstr
Однако я хотел бы знать, является ли этот метод лучшим и самым быстрым способом выполнить это преобразование или есть более простой и быстрый метод (например,встроенный, более умный алгоритм или просто лучший метод).
Я благодарен за ваш вклад.Спасибо.
Решение
Насколько для вас важно «сжать» представление на 18,75%, т. е. с 32 до 26 символов?Потому что, если сохранение этого небольшого процента байтов не является абсолютно необходимым, что-то вроде uid.hex.upper().replace('D','Z')
сделает то, что вы просите (не используя весь алфавит, который вы предоставляете, но единственной ценой этого является отсутствие «сжатия» на 18,75%).
Если сжатие каждого последнего байта имеет решающее значение, я бы работал с подстроками по 20 бит каждая — это 5 шестнадцатеричных символов, 4 символа в вашем прикольном алфавите.Их 6 (плюс 8 бит осталось, за которые можно взять hex.upper().replace
как указано выше, поскольку от чего-то более изысканного нет никакой пользы).Вы можете легко получить подстроки, разрезав .hex
и превратим каждый в int с помощью int(theslice, 16)
.Затем вы можете применить тот же алгоритм, что и выше, но вся арифметика выполняется для гораздо меньших чисел, поэтому прирост скорости должен быть существенным.Кроме того, не создавайте строку, зацикливая ее. +=
-- составить список всех "цифр" и ''.join
их все в конце — это тоже улучшение производительности.
Другие советы
>>> OCRf = 'ABCEGHJKLMNPRSTVWXYZ1234567890+='
>>> uuid = 'a8098c1a-f86e-11da-bd1a-00112444be1e'
>>> binstr = bin(int(uuid.replace("-",""),16))[2:].zfill(130)
>>> ocfstr = "".join(OCRf[int(binstr[i:i+5],2)] for i in range(0,130,5))
>>> ocfstr
'HLBJJB2+ETCKSP7JWACGYGMVW+'
Чтобы конвертировать обратно снова
>>> "%x"%(int("".join(bin(OCRf.index(i))[2:].zfill(5) for i in ocfstr),2))
'a8098c1af86e11dabd1a00112444be1e'
transtbl = string.maketrans(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
'ABCEGHJKLMNPRSTVWXYZ1234567890+='
)
uuidstr = uuid.uuid1()
print base64.b32encode(str(uuidstr).replace('-', '').decode('hex')).rstrip('=').translate(transtbl)
Да, этот метод делает сделай меня немного больным, спасибо, что спросил.