2017-10-12 4 views
0

私は文字列、整数、および倍数を含む "litem"クラスを持っています。私は "myList"と呼ばれるリスト(litem)を持っています。リテームの文字列要素であるlitem.c1に基づいて、myListに重複を見つけることができます。私はそれらの重複要素を、一意のIDを持つ重複したペアにリンクすることによって変更する必要があります。問題は、データが大きく、コードが非常に遅いことです。 myListには220万エントリがあります。私は重複にこの方法を見つける:重複を見つけ、リスト(クラス)を高速に返します

var duplicateItems = myList 
       .AsParallel() 
       .GroupBy(x => x.c1) 
       .Where(x => x.Count() > 1) 
       .Select(x => x.Key) 
       .ToList(); 

これは、約3秒で実行され、重複のlitem.c1値は約40.000の文字列を返します。そして、私が実行します。

var result = myList 
       .AsParallel() 
       .Where(item => duplicateItems.Any(d => d.Equals(item.c1))) 
       .ToList(); 

これは私が必要とする80.000 litemsのリストを返しますが、100%i7のCPUを搭載しながら、それが30分以上実行しています。この後、私はresutにforeachを使用して、見つかった重複リテーム間のリンクを追加します。質問はどのように安い方法で結果を得ることができるのですか?

+0

duplicateItemsは、リストの代わりにHashSet である必要があります。 – schglurps

答えて

0

リストの代わりにハッシュセットを使用し、ハッシュセットにアイテムが含まれているかどうかを確認します。

var duplicateItems = new HashSet<string>(myList 
       .AsParallel() 
       .GroupBy(x => x.c1) 
       .Where(x => x.Count() > 1) 
       .Select(x => x.Key)); 

var result = myList 
       .AsParallel() 
       .Where(item => duplicateItems.Contains(item.c1)) 
       .ToList(); 

これは高速化する必要があります。

FYI、ハッシュセットはスレッドセーフではないため、.AsParallel()がエラーになります。

しかし、私はあなただけで行ういけない理由を本当に理解していけない。むしろ、重複項目のすべてを取得するよりも

var groups = myList 
       .AsParallel() 
       .GroupBy(x => x.c1) 
       .Where(x => x.Count() > 1); 

foreach (var group in groups) 
{ 
    foreach (var value in group) 
    { 
     //duplicate values 
    } 
} 
+0

'List 'はスレッドセーフでもなく、並列処理はコレクションを変更していないので、そのコメントの必要性はなぜですか? –

+0

@CamiloTerevintoハッシュセットからの読み取りもスレッドセーフではないので、 –

+0

ありがとう! 1つの質問:あなたが提案した通りにすれば、グループを作成するときに.ToList()を追加しないでください。私はlitem.c1を変更したくありません。 – Manngo

0

を、のみを通過し、すべてを見つけるために、ちょうど彼らのグループのキーに出て、そのクエリを投影それらのグループの項目のうち、はすでにグループ化されたレコードを使用して、最初のクエリのフロアにドロップするのではなく、2番目のクエリを不要にして結果を得ることができます。

var duplicateItems = myList 
    .GroupBy(x => x.c1) 
    .Where(x => x.Count() > 1) 
    .SelectMany(x => x) 
    .ToList(); 
関連する問題