一致する行が多数あるはずの 2 つのテキスト ファイルがあり、ファイル間で一致する行数を正確に調べたいと考えています。問題は、両方のファイルが非常に大きいことです (1 つのファイルは約 3GB で、もう 1 つのファイルは 16GB を超えています)。そのため、明らかに read() または readlines() を使用してそれらをシステム メモリに読み込むことは、非常に問題になる可能性があります。任意のヒント?私が書いているコードは、基本的に 2 つのループとそれらを比較する if ステートメントだけです。
3 に答える
入力ファイルは非常に大きいため、パフォーマンスを重視する場合は、単純にgrep -f
. この-f
オプションはファイルからパターンを読み取るため、目的の正確なセマンティクスに応じて、必要なことを実行できます。おそらく、-x
行全体の一致のみを取得するオプションも必要でしょう。したがって、Python の全体は次のようになります。
child = subprocess.Popen(['grep', '-xf', file1, file2], stdout=subprocess.PIPE)
for line in child.stdout:
print line
UNIXを使ってみませんgrep
か?ソリューションプラットフォームを独立させたい場合、このソリューションは機能しません。しかし、UNIXでは機能します。Pythonスクリプトからこのコマンドを実行します。
grep --fixed-strings --file=file_B file_A > result_file
また、この問題はmap-reduceを選択する良い理由のようです。
更新0:解明する。--fixed-strings = Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.
と--file= Obtain patterns from FILE, one per line.
つまり、私たちが行っているのは、のコンテンツとfile_B
一致するパターンを取得し、それらをファイル内のパターンのシーケンスとして扱うことです。これがそれをより明確にすることを願っています。file_A
fixed-strings
一致する行の数が必要なので、上記を少し変更しgrep
て数を取得します-
grep --fixed-strings --file=file_B file_A | wc -l
更新1:あなたはこれを行うことができます。まず、各ファイルを1行ずつ個別に調べます。ファイル全体をメモリに読み込まないでください。1行を読み取るときは、この行のmd5ハッシュを計算し、別のファイルに書き込みます。この2つの両方のファイルを実行すると、md5ハッシュで満たされた2つの新しいファイルが取得されます。md5はi/p文字列に関係なく16バイトであるため、これら2つのファイルのサイズが元のファイルよりも大幅に小さいことを期待しています。これで、メモリの問題がほとんどまたはまったくない状態で、おそらくgrepまたはその他の差分手法を実行できます。–srikar3分前編集
更新2:(数日後)これを行うことができますか?table1, table2
mysqlで2つのテーブルを作成します。どちらも2つのフィールドしかありませんid, data
。両方のファイルをこれらの両方のテーブルに1行ずつ挿入します。その後、クエリを実行して重複の数を見つけます。両方のファイルを確認する必要があります。それが与えられました。その事実から逃げることはできません。これで、重複を見つける方法で最適化を行うことができます。MySQLはそのようなオプションの1つです。それはあなたがRAMスペース、インデックス作成などのようにする必要がある多くのことを取り除きます。
ご意見をお寄せいただきありがとうございます。しかし、私がやったことは痛々しいほど単純でした。ファイル全体を読み込むこのようなことを試していました。
file = open(xxx,"r")
for line in file:
if.....
私が最終的にやったことは
for line in open(xxx)
if.....
2 つ目は、ファイルを 1 行ずつ取得します。非常に時間がかかりますが、ほとんど時間がかからずにこれを行うための魔法のような方法はないことを私はほとんど受け入れました:(