2017-10-12 33 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();