当创建Python中的UUID,likeso:

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

何以映射UUID成由大写字母AZ减去字符D,F,I,O,Q和U,加个数字的字符串,加上字符“+”和“=” 。即,从整数或串到所述一组32(比较OCR友好)字符:

[ABCEGHJKLMNPRSTVWXYZ1234567890+=]

我将称此为OCRf集(OCR型)。

我想有一个同构函数:

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

我首先想到的是要经过改变的uuid的过程中基座32 e.g。

OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="

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

不过,我想知道,如果这个方法是去了解这种转换的最佳和最快的方式 - 或者,如果有一个更简单,更快速的方法(如内置,更聪明的算法,或者只是一个更好的方法)。

我对你们的感激输入。谢谢你。

有帮助吗?

解决方案

如何重要的是它给你“挤” 18.75%的表示,即,从32到26个字符?因为,如果节省的字节这个很小的比例也不是绝对关键的,像uid.hex.upper().replace('D','Z')会做什么你问(不使用全字母你提供的信息,但这个问题的唯一成本却丢失了18.75%,“挤压”)。

如果挤下来每个字节是至关重要的,我会在每20位工作子 - 这是5个十六进制字符,在你的时髦的字母4个字符。还有那些6(遗留加8位,以便您可以采取hex.upper().replace如上因为有没有在做任何事情票友获得)。您可以轻松地通过切片.hex得到子,把每一个与一个int(theslice, 16)一个int。然后,你基本上可以运用你上面使用相同的算法 - 但算术上备受小的数字全部完成,所以速度增益应的材料。此外,不要通过循环上+=建立串 - 使所有的“数字”的清单,并''.join他们都在最后 - 这也是一个性能改进

其他提示

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

要再次转换回

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

是,这种方法的的让我有点生病了,感谢要求。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top