1

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

ただし、この方法がこの変換を行うための最良かつ最速の方法であるかどうか、またはより簡単で高速な方法 (組み込み、よりスマートなアルゴリズム、または単に優れた方法など) があるかどうかを知りたいです。

ご意見をお寄せいただきありがとうございます。ありがとうございました。

4

3 に答える 3

2

表現を 18.75%、つまり 32 文字から 26 文字に「絞る」ことは、あなたにとってどれほど重要ですか? この小さな割合のバイトを保存することが絶対に重要ではない場合、次のようなuid.hex.upper().replace('D','Z')ものがあなたが要求することを実行するためです(使用できるアルファベット全体を使用するのではなく、これの唯一のコストはその 18.75% の「圧縮」が失われることです)。

最後のすべてのバイトを圧縮することが重要である場合は、それぞれ 20 ビットの部分文字列で作業します。これは、5 つの 16 進文字、ファンキーなアルファベットの 4 文字です。hex.upper().replaceそれらのうちの6つがあります(さらに8ビットが残っています。これより複雑なことをしても何も得られないため、上記のように取ることができます)。スライスして部分文字列を簡単に取得し、.hexそれぞれをint(theslice, 16). 次に、基本的に上記で使用しているのと同じアルゴリズムを適用できますが、演算はすべてはるかに小さい数値で行われるため、速度の向上は重要です。また、ループして文字列を作成しないでください。+=すべての「数字」のリストを作成''.joinし、最後にそれらすべてを作成します。これもパフォーマンスの向上です。

于 2010-02-17T04:24:54.367 に答える
1
transtbl = string.maketrans(
  'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
  'ABCEGHJKLMNPRSTVWXYZ1234567890+='
)

uuidstr = uuid.uuid1()

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

はい、この方法少し気分が悪くなります。お問い合わせいただきありがとうございます。

于 2010-02-17T08:04:13.883 に答える
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'
于 2010-02-17T04:34:38.120 に答える