4

SQL クエリから 2 つの大きなデータセットを比較しようとしています。現在、SQL クエリは外部で実行され、各データセットの結果は独自の csv ファイルに保存されます。私の小さな C# コンソール アプリケーションは、2 つの text/csv ファイルを読み込み、相違点を比較して、相違点をテキスト ファイルに保存します。

最初のファイルからすべてのデータを arraylist にロードし、各行が 2 番目の csv ファイルから読み取られるときに arraylist で .compare() を実行するだけの非常に単純なアプリケーションです。次に、一致しないレコードを保存します。

アプリケーションは動作しますが、パフォーマンスを改善したいと考えています。両方のファイルがソートされているという事実を利用できれば、パフォーマンスを大幅に改善できると思いますが、順序を維持して特定の位置を選択できる C# のデータ型を知りません。基本的な配列がありますが、各リストにいくつのアイテムが含まれるかはわかりません。100万件以上のレコードを持つことができました。確認する必要がある利用可能なデータ型はありますか?

4

11 に答える 11

2

両方の CSV ファイルのデータが既に並べ替えられていて、同じ数のレコードがある場合は、データ構造を完全にスキップしてインプレース分析を行うことができます。

StreamReader one = new StreamReader("C:\file1.csv");
StreamReader two = new StreamReader("C:\file2.csv");
String lineOne;
String lineTwo;

StreamWriter differences = new StreamWriter("Output.csv");
while (!one.EndOfStream)
{
    lineOne = one.ReadLine();
    lineTwo = two.ReadLine();
    // do your comparison.
    bool areDifferent = true;

    if (areDifferent)
        differences.WriteLine(lineOne + lineTwo);
}

one.Close();
two.Close();
differences.Close();
于 2008-09-16T21:56:47.970 に答える
1

これは、David Sokolのコードをさまざまな行数で機能するように適合させたもので、1つのファイルにはあるが、他のファイルにはない行を出力します。

StreamReader one = new StreamReader("C:\file1.csv");
StreamReader two = new StreamReader("C:\file2.csv");
String lineOne;
String lineTwo;
StreamWriter differences = new StreamWriter("Output.csv");
lineOne = one.ReadLine();
lineTwo = two.ReadLine();
while (!one.EndOfStream || !two.EndOfStream)
{
  if(lineOne == lineTwo)
  {
    // lines match, read next line from each and continue
    lineOne = one.ReadLine();
    lineTwo = two.ReadLine();
    continue;
  }
  if(two.EndOfStream || lineOne < lineTwo)
  {
    differences.WriteLine(lineOne);
    lineOne = one.ReadLine();
  }
  if(one.EndOfStream || lineTwo < lineOne)
  {
    differences.WriteLine(lineTwo);
    lineTwo = two.ReadLine();
  }
}

私の頭のてっぺんから書かれたコードに関する標準的な警告が当てはまります。一方の行がまだ残っているのに、一方の行が不足するという特殊なケースが必要になる場合がありますが、この基本的なアプローチで、探していることを実行できると思います。

于 2008-09-16T22:28:35.660 に答える
1

System.Collections.Specialized.StringCollection を使用すると、値の範囲を追加でき、.IndexOf(string) メソッドを使用して、その項目のインデックスを取得できます。

そうは言っても、ファイルストリームから数バイト [] をロードしてバイト比較を行うことができます... StringCollection や string[]; のような正式なデータ構造にそれらをロードすることについても心配する必要はありません。あなたがしているのは違いをチェックすることだけで、速度が必要な場合は、バイトの違いがどこにあるかを壊します。

于 2008-09-16T21:54:19.427 に答える
0

誰もが非常に多くの異なる答えを持っている理由は、あなたが答えるのに十分にあなたの問題を特定していないからだと思います。まず、追跡する違いの種類によって異なります。WinDiffのように、最初のファイルが「元の」ファイルで、2番目のファイルが「変更された」ファイルのように違いを出力して、変更をINSERT、UPDATE、またはDELETEとしてリストできるようにしますか?同じレコードの異なるバージョンとして2行を一致させることができる主キーがありますか(主キー以外のフィールドが異なる場合)?それとも、これは、差分出力に「ファイル2ではなくファイル1に記録」のように表示させたい、ある種の調整ですか?

これらの質問への回答は、誰もがあなたの問題に適切な答えを与えるのに役立つと思います。

于 2008-09-16T22:13:31.097 に答える
0

まあ、うまくいくいくつかのアプローチがあります。これを行う独自のデータ構造を作成できます。または、SortedListを試して使用することもできます。コードでDataSetを返し、テーブルで.Select()を使用することもできます。確かに、両方のテーブルでこれを行う必要があります。

于 2008-09-16T21:50:39.263 に答える
0

SortedListを簡単に使用して、高速ルックアップを実行できます。ロードしているデータがすでにソートされている場合、SortedListへの挿入が遅くなることはありません。

于 2008-09-16T21:50:50.277 に答える
0

FileAのすべての行がFileBに含まれているかどうかを単に確認したい場合は、それを読み込んで、ループ内のストリームを比較することができます。

ファイル1エントリ1エントリ2エントリ3

ファイル2エントリ1エントリ3

2つのカウンターをループして、欠落を見つけ、各ファイルを1行ずつ調べて、必要なものが得られるかどうかを確認できます。

于 2008-09-16T21:52:24.110 に答える
0

誤解しているかもしれませんが、ArrayListは、要素を追加したときと同じ順序で要素を維持します。これは、1回のパスでのみ2つのArrayListを比較できることを意味します。比較結果に従って、2つのスキャンインデックスをインクリメントするだけです。

于 2008-09-16T21:52:47.417 に答える
0

私が持っている1つの質問は、あなたがあなたの比較を「アウトソーシング」することを検討したかということです。あなたがただ呼び出すことができるたくさんの良いdiffツールがあります。2つのファイルを指定して、違いだけを取得できるファイルがなかったら、私は驚きます。ちょっとした考え。

于 2008-09-16T21:53:22.750 に答える
0

投稿に記載されているように、それぞれ100万行のファイルが2つある場合は、大量のメモリを使用している可能性があります。パフォーマンスの問題のいくつかは、ディスクからスワップしていることである可能性があります。ファイルAの1行目をファイルBの1行目、2行目ファイルA-> 2行目ファイルBなどと単純に比較する場合は、メモリにあまり保存しない手法をお勧めします。以前のコメント投稿者が投稿した2つのファイルストリームの書き込みを読み取り、結果を見つけたら「リアルタイムで」書き出すことができます。これは、メモリに何も明示的に保存しません。また、各ファイルのチャンクをメモリに、たとえば一度に1000行ずつ、リストのようなものにダンプすることもできます。これは、ニーズに合わせて微調整できます。

于 2008-09-16T22:23:30.183 に答える
0

質問 1 を解決するには、各行のハッシュを作成することを検討することをお勧めします。そうすれば、辞書を使用してハッシュをすばやく簡単に比較できます。

質問 2 を解決するには、IDictionary を使用するのが手っ取り早い方法です。itemId を最初の文字列型として使用し、残りの行を 2 番目の文字列型として使用します。その後、itemId が存在するかどうかをすばやく見つけて、行を比較できます。もちろん、これは.Net 2.0+を前提としています

于 2008-09-18T14:05:53.090 に答える