在C#中检查重复项的空值列表

Cem*_*mre 32 c# linq list

在C#中,我可以使用类似的东西:

List<string> myList = new List<string>();

if (myList.Count != myList.Distinct().Count())
{
    // there are duplicates
}
Run Code Online (Sandbox Code Playgroud)

检查列表中的重复元素.但是,当null列表中有项目时,会产生误报.我可以使用一些缓慢的代码来做到这一点,但有没有办法检查列表中的重复项,同时忽略空值的简洁方式?

Raw*_*ing 56

如果您担心性能,以下代码将在找到第一个重复项时立即停止 - 到目前为止所有其他解决方案都要求整个输入至少迭代一次.

var hashset = new HashSet<string>();
if (myList.Where(s => s != null).Any(s => !hashset.Add(s)))
{
    // there are duplicates
}
Run Code Online (Sandbox Code Playgroud)

hashset.Add返回false如果该项目已经存在于集,并Any返回true只要第一个true值出现,所以这只是会尽量搜索输入作为第一个重复.

  • 在我的基准测试+1中,这比我的答案快10倍 (6认同)
  • @Jodrell它会推迟到您尝试读取第一个组的时间点,此时它会读取整个输入序列,对其进行分组,然后返回第一个组. (2认同)
  • @Joe`Distinct`与引擎盖下的`HashSet`基本相同,而且'GroupBy`也会做类似的事情. (2认同)

Dav*_*ish 32

我会这样做:

鉴于Linq语句将被懒惰地评估,.Any意味着短路 - 意味着你不必迭代和计算整个列表,如果有重复 - 并且因此,应该更有效.

var dupes = myList
    .Where(item => item != null)
    .GroupBy(item => item)
    .Any(g => g.Count() > 1);

if(dupes)
{
    //there are duplicates
}
Run Code Online (Sandbox Code Playgroud)

编辑:http://pastebin.com/b9reVaJu一些Linqpad基准测试似乎结束GroupByCount()更快

编辑2:罗林的答案似乎至少比这种方法快5倍!

  • "Any"仍然要求整个输入至少迭代一次(构建组),并且它的某些部分要再次迭代(以检查组的长度 - 尽管第二个想法可能是组可以短路`Count` without iterating) - 尽管可以用*最多*执行这个检查*整个输入的单次迭代. (5认同)

Joe*_*Joe 11

var nonNulls = myList.Where(x => x != null)
if (nonNulls.Count() != nonNulls.Distinct().Count())
{
    // there are duplicates
}
Run Code Online (Sandbox Code Playgroud)