Python UUID表示为特殊字符

时间:2010-02-17 04:07:32

标签: python algorithm uuid transpose isomorphism

在Python中创建UUID时,喜欢:

>>> 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的过程。例如

OCRf = "ABCEGHJKLMNPRSTVWXYZ1234567890+="

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

但是,我想知道这种方法是否是进行此转换的最佳和最快的方法 - 或者是否有更简单快速的方法(例如内置,更智能的算法或更好的方法)。

我很感激您的意见。谢谢。

3 个答案:

答案 0 :(得分:2)

将表示“挤”出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 - 这也是性能改进。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

transtbl = string.maketrans(
  'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
  'ABCEGHJKLMNPRSTVWXYZ1234567890+='
)

uuidstr = uuid.uuid1()

print base64.b32encode(str(uuidstr).replace('-', '').decode('hex')).rstrip('=').translate(transtbl)

是的,这个方法确实让我生病了,谢谢你的提问。