Python UUID rappresentato come caratteri speciali
-
21-09-2019 - |
Domanda
Quando si crea un UUID in Python, likeso:
>>> uuid.uuid1()
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
Come si potrebbe mappa che UUID in una stringa costituita dal capitalizzato alfabeto AZ meno i caratteri D, F, I, O, Q, e U, più le cifre numeriche, più i caratteri "+" e "=" . cioè la da un numero intero o stringa sul set di 32 caratteri (OCR relativamente amichevoli):
[ABCEGHJKLMNPRSTVWXYZ1234567890+=]
Ti chiamo questo il set OCRf
(per OCR amichevole).
Mi piacerebbe avere una funzione isomorfica:
def uuid_to_ocr_friendly_chars(uid)
"""takes uid, an integer, and transposes it into a string made
of the the OCRf set
"""
...
Il mio primo pensiero è quello di passare attraverso il processo di modifica del uuid basare 32. es.
OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="
def uuid_to_ocr_friendly_chars(uid):
ocfstr = ''
while uid > 1:
ocfstr += OCRf[uid % 32]
uid /= 32
return ocfstr
Tuttavia, mi piacerebbe sapere se questo metodo è il modo migliore e più veloce per andare su questa conversione - o se c'è un metodo più semplice e veloce (ad esempio un incorporato, un algoritmo intelligente, o semplicemente un metodo migliore).
Sono grato per il vostro input. Grazie.
Soluzione
Quanto è importante per voi a "spremere" la rappresentazione dal 18,75%, vale a dire, da 32 a 26 caratteri? Perché, se il risparmio questa piccola percentuale di byte non è assolutamente cruciale, qualcosa come uid.hex.upper().replace('D','Z')
farà ciò che si chiede (non usare l'intero alfabeto fate a disposizione, ma l'unico costo di questo è mancante che 18.75% "spremitura").
Se spremere giù ogni ultimo byte è fondamentale, mi piacerebbe lavorare su stringhe di 20 bit ciascuno - che è 5 caratteri esadecimali, 4 personaggi nel vostro alfabeto funky. Ci sono 6 di quelli (più 8 bit lasciati, per i quali si può prendere la hex.upper().replace
come sopra poiché non c'è nulla da guadagnare nel fare qualcosa di più elaborato). Si può facilmente ottenere le stringhe mediante tranciatura .hex
e trasformare ciascuno in un int con una int(theslice, 16)
. Quindi, si può sostanzialmente applicare lo stesso algoritmo si sta utilizzando sopra - ma l'aritmetica è tutto fatto su numeri molto-più piccoli, in modo che il guadagno di velocità dovrebbe essere di materiale. Inoltre, non costruire la stringa da loop su +=
- fare un elenco di tutte le "cifre", e li ''.join
alla fine -. Che è anche un miglioramento delle prestazioni
Altri suggerimenti
>>> 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+'
Per convertire nuovamente
>>> "%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)
Sì, questo metodo non fare di me un po 'malato, grazie per avermelo chiesto.