Pergunta

Ao criar um UUID em Python, assim:

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

Como alguém poderia mapear esse UUID em uma string composta pelo alfabeto AZ maiúsculo menos os caracteres D, F, I, O, Q e U, mais os dígitos numéricos, mais os caracteres "+" e "=".ou sejade um número inteiro ou string para o conjunto de 32 caracteres (relativamente compatíveis com OCR):

[ABCEGHJKLMNPRSTVWXYZ1234567890+=]

Vou chamar isso de OCRf definido (para compatibilidade com OCR).

Eu gostaria de ter uma função isomórfica:

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

Meu primeiro pensamento é passar pelo processo de alteração do uuid para base 32.por exemplo.

OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="

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

No entanto, gostaria de saber se este método é a melhor e mais rápida maneira de fazer essa conversão - ou se existe um método mais simples e rápido (por exemplo,um algoritmo integrado, mais inteligente ou apenas um método melhor).

Estou grato pela sua contribuição.Obrigado.

Foi útil?

Solução

Quão importante é para você “espremer” a representação em 18,75%, ou seja, de 32 para 26 caracteres?Porque, se salvar esta pequena porcentagem de bytes não for absolutamente crucial, algo como uid.hex.upper().replace('D','Z') fará o que você pedir (não usar todo o alfabeto que você disponibiliza, mas o único custo disso é faltar aqueles 18,75% de “aperto”).

Se comprimir até o último byte for crucial, eu trabalharia em substrings de 20 bits cada - são 5 caracteres hexadecimais, 4 caracteres em seu alfabeto descolado.Existem 6 deles (mais 8 bits restantes, para os quais você pode pegar o hex.upper().replace como acima, já que não há nada a ganhar em fazer algo mais sofisticado).Você pode obter facilmente as substrings fatiando .hex e transforme cada um em um int com um int(theslice, 16).Então, você pode basicamente aplicar o mesmo algoritmo usado acima - mas a aritmética é toda feita em números muito menores, então o ganho de velocidade deve ser material.Além disso, não construa a string fazendo um loop += - faça uma lista de todos os "dígitos" e ''.join todos eles no final - isso também é uma melhoria de desempenho.

Outras dicas

>>> 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+'

Para converter novamente

>>> "%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)

Sim, este método faz me deixe um pouco doente, obrigado por perguntar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top