0

ファイルに保存された大きな (2.8 GB) 辞書を効率的に反転 (キーの値と値のキーを交換) するのに問題がありました。効率が問題です。私の現在の解決策は次のとおりです。

  • 辞書ファイルを 1 行ずつ読み込む (形式: ,,,...)

    各行について:

    • 前のパスから進行中の出力ファイルを実行し、 1行ずつ一時ファイルにコピーします。
    • 辞書値 (val1、val2、...) を適切な場所 (アルファベット順) に一時ファイルに挿入し、すべての新しい値を新しいキーにします。
    • 前のパス出力ファイルを一時ファイルで上書きします
    • すべての辞書行が処理されるまで繰り返します (最終的に次の形式になります: :,,,.. :,,.. :,,,..)

このアルゴリズムは非常に扱いにくく、少なくとも出力ファイルは n^2 回 (私は思う...)、n は約 30,000,000 である必要があります。使用可能なメモリが不足していると、全体を読み取ってメモリ内ですべて処理することができなくなります。

そのままにしておくよりも良い解決策はないかもしれませんが、誰かが考えを持っていれば幸いです.

編集:最終的に出力された各行に複数のキーが値として含まれる可能性があることを明確にする必要があります。

4

2 に答える 2

4

次の 3 パス ソリューションをお勧めします。

  1. 元の辞書ファイルを 1 回繰り返し、各 val の出力ファイルに val, key 行を追加します。

  2. UNIX の sort コマンドまたはその他の高速ソート プログラムを使用して、ステップ 1 の出力ファイルをソートします。

  3. ステップ 1 で削除が必要な重複が生成された可能性がある場合は、2 の出力ファイルを繰り返し処理し、最終的な出力ファイルを作成するときに重複を削除します。2 からの出力ファイルは並べ替えられているため、これを行うには 1 つのパスと最小限のメモリしか必要ありません。

于 2013-06-24T22:30:29.997 に答える
1

私はあなたの問題を理解しているかどうかわからないので、あなたが何を望んでいるのかを例を挙げて説明し、それを行う方法を示しましょう。

入力は、次のようなテキスト CSV ファイルです。

a,1,2,3
b,4,5,6
c,7,8,9

各行はキーであり、その後に一連の値が続きます。これは辞書を表し、各値はタプルです (例: d['a'] = (1,2,3).

出力は、次のような CSV ファイルである必要があります。

1,a
2,a
3,a
4,b
5,b
6,b
7,c
8,c
9,c

…しかし、任意の行順序で。元のファイルの各値は、元の行の列 0 のキーにマップされます。(値が重複している場合は、1 つのキーが任意に選択されます。)


したがって、これをすべてメモリ内で行う場合は、次のようになります。

in_dict = {'a': (1, 2, 3), 'b': (4, 5, 6), 'c': (7, 8, 9)}
out_dict = {value: key for key, value_set in in_dict.items() for value in value_set}

唯一の問題は、2.6GB のディクショナリを処理するためにおそらく 5.2GB の RAM が必要になるため、in_dict を独自の形式でディスクに保存し、out_dict を同様の形式でディスクに書き込みたいことです。 、すべてをメモリに読み込むことはありません。

これを行う最も簡単な方法は、中間ストレージに DBM を使用することです。out_dictCSV を DBM に読み込みます。DBM は上記とまったく同じ構造になります。それを書くのはもう少し複雑です。

明らかに、モジュールを使用しcsvて CSV を読み取り (および書き込み)、DBM のモジュールdbm(Python 2.x の場合) を使用する必要があります。anydbm

with contextlib.closing(dbm.open('kv.dbm', 'n')) as db:
    with open('kv.csv') as f:
        for row in csv.reader(f):
            for col in row[1:]:
                db[col] = row[0]

次に、その DBM を好みの形式に書き出します。dbmオブジェクトにメソッドがある場合items、これは次のようになります。

    with open('kvt.csv', 'w') as f:
        csv.writer(f).writerows(dbm.items())

そうでないので、追加するか、genexp を書くことができます:

        csv.writer(f).writerows((key, db[key]) for key in db.keys())

または明示的に繰り返します:

        w = csv.writer(f)
        for key in db.keys():
            w.writerow((key, db[key])

tempfileDBM を一時ファイルにして、使い終わった後に自動的にクリーンアップするためにを使用することもできます。詳細は Windows と *nix 間、および Python のバージョン間で若干異なるため、その部分は読者の演習として残します。

于 2013-06-24T22:56:11.167 に答える