2017-10-12 133 views
0

我有一個類「litem」包含字符串,整數和雙打。我有一個名爲「myList」的List(litem)。我想根據litem.c1在myList中找到重複項,它是litem的一個字符串元素。我需要修改這些重複的元素,將它們連接到具有唯一ID的重複對。問題是我的數據很大,我的代碼很慢。 myList有220萬個條目。我找到了重複這樣:查找重複項並返回列表(類)在一個快速的方式

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

這運行在約3秒,返回約40.000字符串是重複的litem.c1值。然後我運行:

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

這將返回80.000 litems我需要的清單,但它的運行時間超過30分鐘,而100%加載i7處理器。在此之後,我使用一個關於resut的foreach添加找到的重複的litems之間的鏈接。問題是如何以更便宜的方式獲得結果?

+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(); 

這應該加快速度。

僅供參考,hashset isnt線程安全,因此.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

'列表'也不是線程安全的,並行性不會修改集合,那麼爲什麼需要這樣的評論呢? –

+0

@CamiloTerevinto因爲從hashset讀取也不是線程安全的 –

+0

非常感謝!一個問題:如果我按照你的建議去做,我應該在創建組時添加.ToList()嗎?我不想修改litem.c1。 – Manngo

0

而不是讓所有重複的項目,然後突出該查詢出逼到他們組的關鍵,只有經歷並找到所有再次在這些組中的項目中,您可以只使用使用已分組記錄來獲得結果,而不是在第一個查詢中將它們放在地板上,從而使第二個查詢不必要。

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