多くの Google 検索とコードの実験の後、複雑な C# LINQ-to-objects 問題に困惑しました。SQL では、ROW_NUMBER()...PARTITION BY 関数のペアと 1 つまたは 2 つのサブクエリで簡単に解決できます。
つまり、私がコードでやろうとしていることは次のとおりです。根本的な要件は、重複するドキュメントをリストから削除することです。
- まず、(Document.Title, Document.SourceId) でリストをグループ化し、次のような (簡略化された) クラス定義を想定します。
クラス ドキュメント { 文字列のタイトル。 int SourceId; // ソースが優先されます (ID=1 は ID=2 より優れています) }
-
そのグループ内で、各ドキュメントにインデックスを割り当てます (たとえば、インデックス 0 == このソースからのこのタイトルの最初のドキュメント、インデックス 1 = このソースからのこのタイトルの 2 番目のドキュメントなど)。SQL の ROW_NUMBER() に相当するものが欲しいです!
- 今度は (Document.Title, Index) でグループ化します。Index は手順 2 で計算されました。グループごとに、Document.SourceId が最小のドキュメントを 1 つだけ返します。
ステップ 1 は簡単ですが (例: codepronet.blogspot.com/2009/01/group-by-in-linq.html)、ステップ 2 と 3 で困惑しています。3 つの手順すべてを解決するために、赤い波線のない C# LINQ クエリを作成することはできないようです。
このスレッドに関する Anders Heilsberg の投稿は、正しい構文を取得できれば、上記のステップ 2 と 3 に対する答えだと思います。
slodge.blogspot.com/2009/01/adding-row-number-using-linq-to-objects.html で推奨されているように、インデックスの計算を行うために外部ローカル変数を使用することは避けたいと思います。外部変数が変更された場合。
最適には、タイトルによるグループ化のステップを最初に実行できるため、「内部」のグループ化 (最初にソースでインデックスを計算し、次にインデックスで重複を除外する) で、各「タイトルで」少数のオブジェクトを操作できます。各タイトル グループ内のドキュメントの数は通常 100 未満であるため、N 2ソリューションは本当に必要ありません。
ネストされた foreach ループでこれを解決することはできますが、LINQ では単純な問題のように思えます。
何か案は?