Python UUID représenté sous la forme des caractères spéciaux
-
21-09-2019 - |
Question
Lors de la création d'un UUID en Python, likeso:
>>> uuid.uuid1()
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
Comment peut-on carte qui UUID dans une chaîne composée de l'alphabet majuscule AZ moins les caractères D, F, I, O, Q et U, ainsi que les chiffres numériques, ainsi que les caractères « + » et « = » . à savoir le à partir d'un nombre entier ou d'une chaîne sur l'ensemble de 32 caractères (OCR relativement sympathiques):
[ABCEGHJKLMNPRSTVWXYZ1234567890+=]
Je vais appeler cela l'ensemble de OCRf
(OCR friendly).
Je voudrais avoir une fonction isomorphe:
def uuid_to_ocr_friendly_chars(uid)
"""takes uid, an integer, and transposes it into a string made
of the the OCRf set
"""
...
Ma première pensée est de passer par le processus de modification du UUID à la base 32. par exemple.
OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="
def uuid_to_ocr_friendly_chars(uid):
ocfstr = ''
while uid > 1:
ocfstr += OCRf[uid % 32]
uid /= 32
return ocfstr
Cependant, je voudrais savoir si cette méthode est la meilleure et la plus rapide d'aller sur cette conversion - ou s'il y a une méthode plus simple et plus rapide (par exemple une commande interne, un algorithme plus intelligent, ou tout simplement une meilleure méthode).
Je suis reconnaissant pour votre entrée. Merci.
La solution
Quelle importance accordez-vous à la « presser » la représentation de 18,75%, à savoir de 32 à 26 caractères? Parce que, si la sauvegarde de ce petit pourcentage d'octets n'est pas absolument crucial, quelque chose comme uid.hex.upper().replace('D','Z')
fera ce que vous demandez (ne pas utiliser l'alphabet que vous mettez à la disposition, mais le seul coût de ce manque est que 18,75% « presser »).
Si presser vers le bas chaque octet dernier est crucial, je travaille sur 20 bits sous-chaînes de chacun - qui est 5 caractères hexadécimaux, 4 caractères dans votre alphabet funky. Il y a 6 de ceux (plus 8 bits qui restent, pour lesquels vous pouvez prendre le hex.upper().replace
comme ci-dessus car il n'y a rien à gagner à faire quoi que ce soit amateur). Vous pouvez facilement obtenir les sous-chaînes en découpant .hex
et tourner chacun en un int avec un int(theslice, 16)
. Ensuite, vous pouvez appliquer essentiellement le même algorithme que vous utilisez ci-dessus - mais l'arithmétique est fait sur un nombre beaucoup plus-petits, de sorte que le gain de vitesse devrait être matériel. En outre, ne construit pas la chaîne en boucle sur +=
- faire une liste de tous les « chiffres » et ''.join
tous à la fin -. C'est aussi une amélioration de la performance
Autres conseils
>>> 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+'
Pour reconvertir à nouveau
>>> "%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)
Oui, cette méthode Finalité me faire un peu mal, merci de demander.