确定 IEnumerable<> 是否有效的最佳方法具有独特的价值
我有很多代码在其中执行类似的操作
bool GetIsUnique(IEnumerable<T> values)
{
return values.Count() == values.Distinct().Count;
}
是否有更好更快更好的方法来执行此操作?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我会将其作为一个很好的扩展方法
检查所有项目是否都可以添加到 HashSet 中。
I would make this a nice extension method
Checks that all items can be added to a HashSet.
您的方法需要对序列进行两次迭代,但存在一些潜在的缺点:
Count
,每次都需要迭代整个序列。一旦您知道存在重复值,就没有理由不尽早突破。下面的方法只需要遍历序列一次,并且一旦遇到任何重复值就会提前中断:
Your method needs to iterate through the sequence twice, with a few of potential drawbacks:
Count
which needs to iterate the entire sequence each time. There's no reason why you shouldn't break-out early as soon as you know that there's a duplicate value.The following method only needs to iterate through the sequence once, and will break-out early as soon as any duplicate value is encountered:
我认为这取决于您想要做什么(如果存在非唯一值)。 @Jamiec 或 @LukeH 的答案是很好的答案,并且可能对于纯粹的速度来说是最好的,但它不能告诉你问题出在哪里。
您可能还认为像
On it's 本身这样的东西比
HashSet
实现更糟糕。但如果您保留该组,您可以找到哪些元素是重复的。或者
使用
GroupBy
进行思考,让您可以对下一步做什么保持开放的选择。但是,如果您关心的只是知道所有值是否都是唯一的,我会选择HashSet
I think it depends on what you want to do if there are non unique values. @Jamiec's Or @LukeH's answer are great answers and probably best for pure speed, but it can't tell you where issues are.
You might also consider something like
On it's own its worse than the
HashSet
implementation. But if you keep that group around you can find which elements are duplicated.Or
Thinking about it with
GroupBy
lets you keep your options open for what to do next. But if all you care about is knowing if all values are unique I'd go with theHashSet
您将对上述数据进行两次循环 - 一次获取计数,一次获取不同计数。如果前两项相同,那就更糟糕了!尝试这样的操作:
一旦找到重复项,该操作就会完成。显然,它取决于哈希查找的速度,但考虑到 Distinct 在内部使用了一个集合,我仍然希望它更快。
You would be doing two loops through the data for the above - once to get the count, once to get the distinct count. Especially bad if the first two items are identical! Try something like this:
This one will finish as soon as it finds a duplicate. Obviously it on the speed of the hash lookup but given Distinct uses a set internally I'd still expect it to be quicker.
两个基本规则:
其他方法会更快(当找到重复值时它们会短路,返回 false),但是,如果这是我的代码,我仍然会坚持使用你的版本。
Two basic rules:
The other methods are going to be faster (they'll short circuit when a repeated value is found, returning false), but, I'd still stick with your version if it were my code.
查找第一个重复项(如果存在)的快速方法是:
A quick way of finding the first duplicate, if present, is:
我很惊讶还没有人测试过这个:
将问题中的 Gluip 版本与 JamieC、LukeK 和 MrKWatkins 进行比较,所有三个答案都比提问者的版本更好。
在这三个答案中,它们都相当具有可比性,但在大多数情况下,JamieC 的速度稍快一些。
当数据没有重复项或重复项位于 IEnumerable 末尾时,大小或算法没有重大差异。
当数据在中间或开头附近有重复项时,原始问题中的 Gluip 版本显示与其他三个版本相比其速度较慢。
检查集合的时间似乎与集合的大小成线性比例,这意味着没有算法更适合大型或小型集合。
下面是一个测试程序,它会生成一个 CSV 文件,您可以将其加载到电子表格程序中,并根据需要进行排序和绘制图表:
测试程序:
I'm suprised no one has tested this just yet:
Comparing Gluip's version in the question with JamieC, LukeK, and MrKWatkins, All three answers are better than the asker's version.
Of the three answers, they are all pretty comparable but in most case JamieC's is slightly faster.
When the data has no duplicates or a duplicate is at the end of the IEnumerable, the size or algorithm had no major differences.
When the data has a duplicate near the middle, or at the beginning, Gluip's version in the original question shows its slowness compared to the other three.
The time to check a set appears to scale linearly with the size of set, meaning no algorithm is preferable for large or small sets.
Here's a test program that spits out a CSV that you can load into a spreadsheet program and sort and graph if you like:
Test Program: