2010-11-27 28 views
3

以下のコードでは連結がボトルネックです。 私はこれをスピードアップするための洗練された方法を試しましたが、とにかくその血まみれは遅くなりました。私はそれを甘やかすために何かできるかどうかを知りたい。Pythonで文字列の連結を高速化する方法はありますか?

ところで、プレーンと秘密の両方のバイナリファイルから読み込まれたデータであり、彼らは(1メガバイトの周りに)かなり大きいです

x = b'' 
if len(plain) < len(secret*8): 
    return False 
i = 0 

for secByte in secret: 
    for j in range(8): 
     z = setBit(plain[i],0,getBit(secByte,j)) 
     #x += bytes([z]) 
     x = x.join([b"", bytes([z])]) 
     #x = array.array("B",(int(z) for z in x.join([b"", bytes([z])]))).tostring() 
     i = i+1 
+0

は、あなたがしようとしているものの擬似コードのような簡単な「C」を追加することができますか?私はPythonでsetBitに慣れていません... –

+0

文字列の連結方法とスピードについては、以下を参照してください。http://stackoverflow.com/questions/1316887/what-is-the-most-efficient-string-concatenation-method-in- Python – mshsayem

+0

。 。 。 http://stackoverflow.com/questions/1349311/python-string-join-is-faster-than-but-whats-wrong-here – mshsayem

答えて

5

私はあなたがすべてで、このための文字列の連結を使用しなければならないとは思いません。最終データのフルサイズの変更可能なbytearrayを作成し、各バイトを設定する方が良いでしょう。これは非常にO(N)であり、あなたがbytearrayを使用してやっていることのためにはるかに自然な文字列操作より:

x = bytearray(len(secret)*8) # creates an array of zero bytes 
i = 0 
for secByte in secret: 
    for j in range(8): 
     x[i] = setBit(plain[i], 0, getBit(secByte, j)) 
     i += 1 
+0

これはちょうど私が必要としたものです(それは100倍速く動作します) xscottの解決策はこれほど速く、これは私の問題に適しています – sowa

7

Pythonのリストは、少なくとも償却意味で、Oは、(1)追加しています。最も内側のリストで結合を行うのではなく、1つの大きなリストを作成して、最後に結合することができます。これはあなたのアルゴリズムをO(N^2)からO(N)に変えます。それはあなたのsetBit()とgetBit()関数がやっている正確に何を知らなくても、コードを作業与えるために厳しいですが、何かのように:

L = [] 
for secByte in secret: 
    for j in range(8): 
     z = ... 
     L.append(z) 
x = b"".join(L) 
+1

これはPython 2.3以降は当てはまりませんでした。いくつかのコードを結合したり結合したりしてください。 –

+3

@nate c、Python文字列は、連続したバイトとそれに関連する長さの配列です。 x.join(...)を使った彼のコードは、古い文字列が割り当てられたときにその文字列を解放する前に、新しい文字列を作成します。これはO(N^2)の動作です。あなたは間違っていて、あなたは私を改造してはいけません。 – xscott

+2

リストとして文字列を作成し、必要に応じて(リスト全体を作成した後に)結合するという提案は、これまでのところ私の知る限り有効です。非常に長い間、Pythonの習慣として推奨されてきました。 –

関連する問題