Pregunta

Al crear un UUID en Python, likeso:

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

¿Cómo podría un mapa que UUID en una cadena formada por el alfabeto en mayúsculas AZ menos los caracteres D, F, I, O, Q y T, además de los dígitos numéricos, además de los caracteres "+" y "=" . es decir, el de un número entero o cadena sobre el conjunto de 32 caracteres (OCR relativamente Friendly):

[ABCEGHJKLMNPRSTVWXYZ1234567890+=]

Voy a llamar a este conjunto OCRf (OCR para usar).

Me gustaría tener una función isomorfo:

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

Mi primer pensamiento es que pasar por el proceso de cambiar el UUID basar 32. por ejemplo.

OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="

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

Sin embargo, me gustaría saber si este método es la mejor y más rápida manera de hacer esta conversión - o si hay un método más simple y más rápido (por ejemplo, una orden interna, un algoritmo inteligente, o simplemente un método mejor).

Estoy agradecido por su entrada. Gracias.

¿Fue útil?

Solución

¿Qué tan importante es para usted "exprimir" la representación un 18,75%, es decir, de 32 a 26 caracteres? Porque, si el ahorro de este pequeño porcentaje de bytes no es absolutamente crucial, algo así como uid.hex.upper().replace('D','Z') hará lo que le preguntas (no usar todo el alfabeto que ponga a disposición, pero el único costo de esto es que falta que el 18,75% "exprimir").

Si apretando hacia abajo hasta el último byte es fundamental, yo trabajaría en subseries de 20 bits cada uno - que es 5 caracteres hexadecimales, 4 caracteres en el alfabeto moderno. Hay 6 de ellos (más de 8 bits sobrantes, para lo cual se puede tomar el hex.upper().replace que el anterior ya que no hay nada que ganar en hacer nada más elegante). Usted puede conseguir fácilmente las subseries por corte .hex y girar cada uno en un int con un int(theslice, 16). Entonces, básicamente se puede aplicar el mismo algoritmo que está utilizando anterior - pero la aritmética se hace todo en números mucho más pequeños, por lo que la ganancia de velocidad debe ser de importancia. Además, no construir la cadena haciendo un bucle en += - hacer una lista de todos los "dígitos", y ''.join todos ellos al final -. Eso es también una mejora de rendimiento

Otros consejos

>>> 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 convertir de nuevo

>>> "%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í, este método hace hacerme un poco enferma, gracias por preguntar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top