AQuickWaytoCheckIEnumerableContainsDuplicates(=isdistinct)?起初我开始:varenumAsArray=enum.ToArray();if(enumAsArray.Length!=enumAsArray.Distinct().Count())throw...但是,这看起来像O(2n)-是吗?ToArray()可能是O(1)?这看起来更快:varset=newHashSet();foreach(varstrinenum){if(!set.Add(str))throw...}这应该是O(n),但是,是否还有内置方式?编辑:也许Distinct()在内部使用这个?解决方案:在考虑了所有评论和答案之后,我为第二个解决方案编写了一个扩展方法,因为这似乎是最快和最易读的版本:publicstaticboolContainsDuplicates(thisIEnumerablee){varset=newHashSet();//ReSharper禁用LoopCanBeConvertedToQueryforeach(varitemine)//ReSharper恢复LoopCanBeConvertedToQuery{if(!set.Add(item))returntrue;}返回假;你的第二个代码示例简短、简单,而且显然有效,如果不是非常理想的解决方案,那么显然非常接近它。对于您的特定问题,这似乎是一个完全可以接受的解决方案,除非您已经注意到该问题并进行了性能测试,表明使用该特定解决方案会导致性能问题,否则我将保持原样。鉴于我总体上看不到改进的空间,这似乎不太可能。这不是一个足够冗长或复杂的解决方案,尝试找到“更短”或更简洁的解决方案值得您花时间和精力。简而言之,您的代码中几乎肯定有更好的地方可以花费您的时间;你已经很好了。回答您的具体问题:但是,这看起来像O(2n)-是吗?是的。ToArray()可能是O(1)?不,这是不对的。也许Distinct()在内部使用它?它确实使用了一个HashSet,看起来非常相似,但它只是忽略了重复项;它没有向调用者表明它刚刚传递了一个重复项。所以你需要将整个序列迭代两次,看看它是否删除了什么,而不是在遇到第一个副本时停止。这就是总是将整个序列迭代两次和可能将整个序列迭代一次但一旦确定答案就会短路并停止的东西之间的区别。也有内置的方式吗?好吧,你展示了一个,它只是效率不高。我认为没有像您展示的那样基于LINQ的高效解决方案。我能想到的最好的是:data.Except(data).Any()。这比普通计数好一点,因为第二次迭代可以短路(但不是第一次),但它也迭代序列两次,并且仍然比非LINQ解决方案差,所以它仍然不值得使用。这是对OP答案的可能改进:publicstaticIEnumerableDuplicates(thisIEnumerablee){varset=newHashSet();//ReSharper禁用LoopCanBeConvertedToQueryforeach(varitemine)//ReSharper恢复LoopCanBeConvertedToQuery{if(!set.Add(item))yieldreturnitem;你现在有一个潜在有用的方法来获取实际的重复项,你可以用以下方法回答原始问题:collection.Duplicates().Any()只是对现有解决方案的补充items){returnContainsDuplicates(items,EqualityComparer.Default);}publicstaticboolContainsDuplicates(thisIEnumerableitems,IEqualityComparerequalityComparer){forvarset=newHashSet(equalityinComparer)items){if(!set.Add(item))returntrue;}返回假;这个版本允许你选择一个相等比较器,如果你想根据非默认规则比较项目,这会很有用。例如,要比较一组不区分大小写的字符串,只需将StringComparer.OrdinalIgnoreCase传递给它即可。以上就是C#学习教程:快速查看IEnumerable是否包含重复项(=不重复)。如果对大家有用,需要进一步了解C#学习教程,希望大家多加关注——本文来自网络合集,不代表立场,如涉及侵权,请点击有权联系管理员删除。如需转载请注明出处:
