Python UUID представлен в виде специальных символов

1

При создании UUID в Python, likeo:

>>> uuid.uuid1()
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')

Как можно сопоставить этот UUID в строку, состоящую из заглавного алфавита AZ, за вычетом символов D, F, I, O, Q и U, плюс числовые цифры плюс символы "+" и "=", то есть из целого числа или строки на набор из 32 (относительно дружественных к OCR) символов:

[ABCEGHJKLMNPRSTVWXYZ1234567890+=]

Я назову это набором OCRf (для дружественного OCR).

Я хотел бы иметь изоморфную функцию:

def uuid_to_ocr_friendly_chars(uid)
    """takes uid, an integer, and transposes it into a string made 
       of the the OCRf set
    """
    ...

Моя первая мысль заключается в том, чтобы пройти процесс изменения uuid на базовую 32. например

OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="

def uuid_to_ocr_friendly_chars(uid):
     ocfstr = ''
     while uid > 1:
        ocfstr += OCRf[uid % 32]
        uid /= 32
     return ocfstr

Тем не менее, я хотел бы знать, является ли этот метод лучшим и быстрым способом для этого преобразования - или если есть более простой и быстрый метод (например, встроенный, более интеллектуальный алгоритм или просто лучший метод).

Я благодарен за ваш вклад. Спасибо.

Теги:
algorithm
uuid
isomorphism
transpose

3 ответа

2
Лучший ответ

Насколько важно вам "сжать" представление на 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 все их в конце - это также улучшит производительность.

  • 0
    Согласитесь космический трепет - хорошая точка - хотя есть (астрономически удаленная) вероятность столкновений с .replace ('O', 'D') / и т. д. Более важным моментом было бы иметь сокращенный, хотя и «прикольный» алфавит, который использует меньше визуально неоднозначных символов (например, «D», «O», «Q» и «0»).
  • 0
    @ Брайан, я не вижу, какие "коллизии" могут возникнуть, если вы просто используете uid.hex.upper().replace('D', 'Z') . «D» - единственный символ в шестнадцатеричном наборе, который может быть смешан с другим («0», цифра ноль)
Показать ещё 1 комментарий
1
transtbl = string.maketrans(
  'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
  'ABCEGHJKLMNPRSTVWXYZ1234567890+='
)

uuidstr = uuid.uuid1()

print base64.b32encode(str(uuidstr).replace('-', '').decode('hex')).rstrip('=').translate(transtbl)

Да, этот метод делает меня немного больным, спасибо за вопрос.

1
>>> 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'
  • 1
    Нет необходимости в причудливости с binstr - вы можете просто получить свойство .bytes для UUID, чтобы получить его двоичное представление.
  • 0
    @ Ник Джонсон, можешь объяснить, что ты имеешь в виду? Я не вижу, как я могу перегруппировать .bytes качестве базы 32
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню