2

文字列の長いリストを圧縮する必要があります。個別に圧縮する必要があります。各文字列の長さは1000文字未満です。ただし、これらの文字列の多くには共通のプレフィックスがあります。したがって、最初に共通のプレフィックスを圧縮してから、コンプレッサーの状態を保存し、それに文字列のサフィックスをフィードすることで、圧縮コストを償却できるかどうか疑問に思いました。

Pythonでこれを実現する方法について何か提案があれば、それは素晴らしいことです。タイトルでzlibについて言及していますが、他の標準モジュールも機能します。このアプリケーションでは、解凍の速度はそれほど重要ではないので、解凍をかなり遅くする余裕があります。

4

1 に答える 1

2

zlibへのPythonインターフェースはかなり貧弱であり、 zlibのすべての機能へのアクセスを提供するわけではありません。zlibへの独自のインターフェースを構築できる場合は、求めていることなどを実行できます。

「その他」は、非常に短い文字列を個別に圧縮しているという事実と関係があります。これにより、取得できる圧縮量が本質的に制限されます。これらの文字列にはいくつかの共通の内容があるため、およびを使用する必要がありdeflateSetDictionary()ますinflateSetDictionary()その事実を利用し、圧縮を大幅に改善する可能性のあるzlibの機能。共通コンテンツは、言及した共通プレフィックス、および文字列内の他の場所の共通コンテンツにすることができます。文字列に一般的に現れるバイトのシーケンスを含む最大32Kのすべての文字列に使用する固定辞書を定義します。最も一般的なシーケンスを32Kの最後に配置し、あまり一般的でないシーケンスを前に配置します。共通のシーケンスが異なるこれらの文字列のクラスが複数ある場合は、辞書のセットを作成し、の最初の呼び出しから返された辞書IDを使用して辞書inflate()を選択できます。1つまたは複数のディクショナリの場合、同じディクショナリが圧縮側と解凍側の両方に格納されていることを確認する必要があります。

圧縮状態の保存については、で行うことができますdeflateCopy()。これは、Pythonでcopy()メソッドとともに提供されます。小さな弦の場合でも、それがスピードのアドバンテージになるかどうかはわかりません。

アップデート:

最近追加されたコメントから、あなたのユースケースは、リクエストに応じて多くの文字列のいくつかを受信者に送信することだと思います。この場合、わずかなPythonインターフェースを使用して、はるかに優れた圧縮を実現する方法があるかもしれません。このflushメソッドを使用しZ_SYNC_FLUSHて、これまでに圧縮されたものを出力に強制することができます。これにより、要求された一連の文字列を単一の圧縮ストリームとして扱うことができます。

プロセスは、で圧縮オブジェクトを開始し、要求された最初の文字列でそのオブジェクトをcompressobj()使用し、その出力(存在する場合)を収集してから、オブジェクトに対してを実行し、残りの出力を収集することです。との結合された出力をレシーバーに送信します。レシーバーは、を開始し、送信されたものとともにそのオブジェクトを使用します。これにより、元の文字列が返されます。(減圧側でフラッシュは必要ありません。)compress()flush(Z_SYNC_FLUSH)compress()flush()decompressobj()decompress()

これまでのところ、結果はその最初の文字列を圧縮することと大差ありません。良い部分は、新しい圧縮または解凍オブジェクトを作成せずにそのプロセスを繰り返すことです。次の文字列にはとを使用compress()し、もう一方の端ではそれを取得します。2番目の文字列、および後続のすべての文字列の利点は、前の文字列の履歴を圧縮に使用できることです。そうすれば、固定辞書を作成したり使用したりする必要はありません。以前に要求された文字列の履歴を使用して、適切な圧縮に必要な飼料を提供できます。文字列の平均長が1000バイトの場合、圧縮用のスライディングウィンドウの長さは32Kであるため、最終的に送信される各文字列は、最後に送信された32文字列の履歴の恩恵を受けます。flush()decompress()

完了したら、オブジェクトを閉じるだけです。

于 2012-07-26T13:44:06.063 に答える