我一直在努力寻找一种从列表中查找唯一值数量的好方法。有一个非常好的问题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方法。
当唯一关心的是执行此任务的速度时,您认为最佳方法是什么?
答案 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)
对于List
和eastings
使用HashSet代替northings
,您可以提高速度:
HashSet<double> eastings = new HashSet<double>();
HashSet<double> northings = new HashSet<double>();
这会更快的原因是因为HashSet
使用哈希来提供O(1)
查找,而不是使用List
O(n)
(它必须搜索)整个列表以查看该项目是否存在。)