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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top