在 C# 中,我可以使用类似的东西:
List<string> myList = new List<string>();
if (myList.Count != myList.Distinct().Count())
{
// there are duplicates
}
检查列表中的重复元素。但是,当列表中有null
项目时,这会产生误报。我可以使用一些缓慢的代码来做到这一点,但是有没有办法检查列表中的重复项,同时以简洁的方式忽略空值?
如果您担心性能问题,以下代码将在找到第一个重复项后立即停止 - 到目前为止,所有其他解决方案都要求整个输入至少迭代一次。
var hashset = new HashSet<string>();
if (myList.Where(s => s != null).Any(s => !hashset.Add(s)))
{
// there are duplicates
}
hashset.Add
false
如果该项目已经存在于集合中,则返回,并在第一个值出现时立即Any
返回,因此这只会搜索输入,直到第一个重复项。true
true
我会这样做:
鉴于 Linq 语句将被延迟评估,因此.Any
将短路 - 这意味着如果有重复项,您不必迭代和计算整个列表 - 因此,应该更有效。
var dupes = myList
.Where(item => item != null)
.GroupBy(item => item)
.Any(g => g.Count() > 1);
if(dupes)
{
//there are duplicates
}
编辑:http : //pastebin.com/b9reVaJu 一些似乎结束GroupBy
的Linqpad 基准测试Count()
更快
编辑 2: 下面罗林的回答似乎比这种方法至少快 5 倍!
var nonNulls = myList.Where(x => x != null)
if (nonNulls.Count() != nonNulls.Distinct().Count())
{
// there are duplicates
}
好吧,两个空值是重复的,不是吗?
无论如何,比较没有空值的列表:
var denullified = myList.Where(l => l != null);
if(denullified.Count() != denullified.Distinct().Count()) ...
编辑我的第一次尝试很糟糕,因为它没有被推迟。
反而,
var duplicates = myList
.Where(item => item != null)
.GroupBy(item => item)
.Any(g => g.Skip(1).Any());
删除了较差的实现。