2016-05-16 1 views
0

私の質問は非常にシンプルですが、適切な答えはどこにも見つかりませんでした。 。の.txtファイルを読み込み、重複行があるかどう、1を保持していない、それらのすべてを削除する方法たとえば、.TXTに次のものが含まれます。PHPを使ってファイル内の重複した行を削除するにはどうすればいいですか?(オリジナルのものを含む)

1234 
1233 
1232 
1234 

出力は次のようになります。

1233 
1232 

コードは複製された行をすべて削除する必要があるため、すべてのWebを検索しましたが、常にrem複製された行は削除されますが、thisthis、またはthatのように、それらの1つを保持します。

これを実行する唯一の方法は、x行を読み込んで、.txt全体をチェックして、同じ結果を見つけたら、x行も削除して削除することです。そうでない場合は、次の行に変更します。しかし、私がチェックしている.txtファイルには50億の行(〜900Mb)があります。このような仕事をするためにどれくらいのメモリが必要かわからないので、ここで助けてください。

+0

をあなたは私の解決策をテストすることができる場合、私は興味がある...特別にそのメモリフットプリントについて:) –

+0

出力ファイルの行の順序は重要ですか? – Mike

+0

努力していただきありがとうございます、あなたのコードは小さなファイルで動作することができますが、私はそのために十分なメモリがないため、50百万のエントリでコードをテストできません... –

答えて

3

ファイルを1行ずつ読み込み、値が行が表示される回数をカウントする連想配列のキーとして使用します。完了したら、値が1のすべての行を書き出します。これには、すべてのユニークな行と同じくらいのメモリが必要です。

$lines = array(); 
$fd = fopen("inputfile.txdt", "r"); 
while ($line = fgets($fd)) { 
    $line = rtrim($line, "\r\n"); // ignore the newline 
    if (array_key_exists($line, $lines)) { 
     $lines[$line]++; 
    } else { 
     $lines[$line] = 1; 
    } 
} 
fclose($fd); 
$fd = fopen("outputfile.txt", "w"); 
foreach ($lines as $line => $count) { 
    if ($count == 1) { 
     fputs($fd, "$line" . PHP_EOL); // add the newlines back 
    } 
} 
+0

もし900MBのデータを持っているので、この方法では重複がなければかなりのRAMが必要になることに注意してください。また、行の平均長さが平均的に長い場合は、コンテンツ自体の代わりに行のハッシュを配列キーとして使用するほうが良いかもしれません。 –

+0

@dragoste真実ですが、すべての重複を削除する前に、ファイル全体をメモリに読み込む答えよりも優れています。彼の例には短い行があるので、私は長い行に適した解決策を見せないように決めました。 – Barmar

+0

確かに、それは良いです、そして、それが私の考えを指摘するためにあなたの答えを選んだ理由です。 –

0

私はあなたがしたいことのすべてを行う唯一の機能があるとは思っていません。したがって、これはステップに分解されます...

まず、ファイルを直接アレイにロードできますか?今fileコマンド

$lines = file('mytextfile.txt'); 

のマニュアルを参照してください、私は、アレイ内のすべての行を持っています。私が持っている各エントリーの数を数えたいと思う。 array_count_valuesコマンドのドキュメントを参照してください。今

$counts = array_count_values($lines); 

、Iはアレイを通して容易にループすることができ、カウント> 1

foreach($counts as $value=>$cnt) 
    if($cnt>1) 
    unset($counts[$value]); 

は今、私は配列に(値)配列のキーを回すことができる任意のエントリを削除します。

$nondupes = array_keys($counts); 

最後に、内容をファイルに書き出すことができます。

file_put_contents('myoutputfile.txt', $nondupes); 
+0

CLIまたはブラウザでこのコードを実行する予定ですか? PHPのメモリと時間制限にぶつからないようにCLIで実行することをお勧めします。 –

+0

@AmbroiseMaupate彼はWeb経由で5,000万行を解析している場合、デフォルトのインストールでメモリまたは時間制限のいずれかにぶつかります。それは彼のせいだ。 – kainaw

+0

彼がこのすべてのデータをSQLデータベースに追加すればどうなるでしょうか?次に、単純なSQLクエリを作成して、重複したエントリを見つけることができます。 SQLiteのみでは、追加の設定は必要ありません(php-sqlite拡張を設定した場合)。 –

0

私ははるかにエレガントな解決策を持っていると思う:

$array = array('1', '1', '2', '2', '3', '4'); // array with some unique values, some not unique 

$array_count_result = array_count_values($array); // count values occurences 

$result = array_keys(array_filter($array_count_result, function ($value) { return ($value == 1); })); // filter and isolate only unique values 

print_r($result); 

ができます:

Array 
(
    [0] => 3 
    [1] => 4 
) 
関連する問題