查找列表中唯一成员数量的最快方法

时间:2016-01-14 17:19:15

标签: c# linq

我一直在努力寻找一种从列表中查找唯一值数量的好方法。有一个非常好的问题here,我试图仔细阅读,以创建一个如下所示的解决方案:

gridStats[0] = gridList.SelectMany(x => x.Position.Easting).Distinct().ToList().Count();
gridStats[1] = gridList.SelectMany(x => x.Position.Northing).Distinct().ToList().Count();

然而,这似乎产生了一个错误,说我隐含地声明了没有意义的类型参数。进一步的研究似乎表明,“Distinct”虽然很好,但实际上并没有提供我想要的东西,如果没有一些额外的代码。

因此,我放弃了这种方法并试图采用循环方法,我已经达到了这个目的:

List<double> eastings = new List<double>();
List<double> northings = new List<double>();

for (int i = 0; i < gridList.Count; i++)
{
    if (!eastings.Contains(gridList[i].Position.Easting))
    {
        eastings.Add(gridList[i].Position.Easting);
    }

    if (!northings.Contains(gridList[i].Position.Northing))
    {
        northings.Add(gridList[i].Position.Northing);
    }
}

gridStats[0] = eastings.Count;
gridStats[1] = northings.Count;

请注意,'gridList'可能有数亿个条目。

可以预见,这个循环使用起来并不是特别快。因此,我希望能够在提高循环效率方面获得帮助,或者帮助整理Linq方法。

当唯一关心的是执行此任务的速度时,您认为最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

你太近了。

Distinct确实是这种情况的最佳选择 - 它类似于基于HashSet<T>的实现,但在内部使用了一个特殊的轻量级哈希集实现。在实践中,我认为性能没有明显的差异,但Distinct仍然更具可读性,同时更快一点。

您错过的是链接中的问题是关于具有列表属性的对象列表,因此它需要SelectMany,而在您的情况下,对象包含< strong>单一属性,所以一个简单的Select将完成这项工作,就像这个

gridStats[0] = gridList.Select(x => x.Position.Easting).Distinct().Count();
gridStats[1] = gridList.Select(x => x.Position.Northing).Distinct().Count();

另请注意,为了使用ToList扩展方法,不需要Count次调用。每个操作都有成本,所以不要包含不必要的方法 - 它们不会使你的代码更具可读性,但肯定会使它更慢,更节省空间。

答案 1 :(得分:1)

对于Listeastings使用HashSet代替northings,您可以提高速度:

HashSet<double> eastings = new HashSet<double>();
HashSet<double> northings = new HashSet<double>();

这会更快的原因是因为HashSet使用哈希来提供O(1)查找,而不是使用List O(n)(它必须搜索)整个列表以查看该项目是否存在。)