在C#中,我可以使用类似的东西:
List<string> myList = new List<string>();
if (myList.Count != myList.Distinct().Count())
{
// there are duplicates
}
检查列表中的重复元素。但是,如果列表中有null
项,则会产生误报。我可以使用一些缓慢的代码来做到这一点但有没有办法检查列表中的重复项,同时以简洁的方式忽略空值?
答案 0 :(得分:56)
如果您担心性能,下面的代码会在找到第一个重复项后立即停止 - 到目前为止所有其他解决方案都要求整个输入至少迭代一次。
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
,因此只会搜索输入到第一个副本。
答案 1 :(得分:32)
我的方式不同:
鉴于Linq语句将被懒惰地评估,.Any
将短路 - 意味着您不必迭代&amp;计算整个列表,如果有重复项 - 并且因此应该更有效。
var dupes = myList
.Where(item => item != null)
.GroupBy(item => item)
.Any(g => g.Count() > 1);
if(dupes)
{
//there are duplicates
}
编辑:http://pastebin.com/b9reVaJu一些Linqpad基准测试似乎与GroupBy
结束Count()
更快
编辑2:罗林的答案似乎至少比这种方法快5倍!
答案 2 :(得分:11)
var nonNulls = myList.Where(x => x != null)
if (nonNulls.Count() != nonNulls.Distinct().Count())
{
// there are duplicates
}
答案 3 :(得分:4)
嗯,两个空值是重复的,不是吗?
无论如何,比较没有空值的列表:
var denullified = myList.Where(l => l != null);
if(denullified.Count() != denullified.Distinct().Count()) ...
答案 4 :(得分:1)
编辑我的第一次尝试很糟糕,因为它没有推迟。
代替,
var duplicates = myList
.Where(item => item != null)
.GroupBy(item => item)
.Any(g => g.Skip(1).Any());
删除较差的实施。