测试两个IEnumerable 是否具有相同频率的相同值
我有两个多字节,都是IEnumerables,我想比较它们。
string[] names1 = { "tom", "dick", "harry" };
string[] names2 = { "tom", "dick", "harry", "harry"};
string[] names3 = { "tom", "dick", "harry", "sally" };
string[] names4 = { "dick", "harry", "tom" };
希望names1 == names4返回true(并且self == self显然返回true)
但所有其他组合都返回错误。
什么是最有效的方式? 这些可以是大型复杂对象。
我看着做:
var a = name1.orderby(v => v.Name);
var b = name4.orderby(v => v.Name);
return a == b;
最有效的方法取决于数据类型。 一个非常短的合理有效的O(N)解决方案如下:
var list1Groups=list1.ToLookup(i=>i); var list2Groups=list2.ToLookup(i=>i); return list1Groups.Count == list2Groups.Count && list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
这些项目必须具有有效的Equals
和GetHashcode
实现。
如果你想要一个更快的解决方案,下面的cdhowie解决方案是相对快的@ 10000元素,并且对于大型简单对象集合提前5倍 – 可能是由于更好的内存效率。
最后,如果你真的对性能感兴趣,我肯定会尝试 Sort-then-SequenceEqual方法。 虽然它的复杂性更差,但这只是一个log N
因子,并且绝对可以通过所有实际数据集大小的常量差异来淹没 – 并且您可能能够就地排序,使用数组甚至递增排序(这可以是线性的)。 即使是40亿个元素,log-base-2也只有32个; 这是一个相关的性能差异,但恒定因子的差异可以想象得更大。 例如,如果你正在处理整数数组并且不介意修改集合顺序,那么即使对于10000000个项目(以下两次,我得到32位的OutOfMemory),以下速度也比任何一个选项都要快:
Array.Sort(list1); Array.Sort(list2); return list1.SequenceEqual(list2);
YMMV取决于机器,数据类型,月球周期以及影响微基准的其他常见因素。
首先排序,然后使用Enumerable.SequenceEqual
。 如果类型实现IEquatable
或覆盖Equals
,则可以使用第一个重载; 否则你将不得不使用第二个表单并提供自己的IEqualityComparer
。
因此,如果您的类型确实实现了相等,那么只需:
return a.SequenceEqual(b);
这是另一个更快,更安全,无需排序的选项:
public static bool UnsortedSequencesEqual( this IEnumerable first, IEnumerable second) { return UnsortedSequencesEqual(first, second, null); } public static bool UnsortedSequencesEqual ( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { if (first == null) throw new ArgumentNullException("first"); if (second == null) throw new ArgumentNullException("second"); var counts = new Dictionary(comparer); foreach (var i in first) { int c; if (counts.TryGetValue(i, out c)) counts[i] = c + 1; else counts[i] = 1; } foreach (var i in second) { int c; if (!counts.TryGetValue(i, out c)) return false; if (c == 1) counts.Remove(i); else counts[i] = c - 1; } return counts.Count == 0; }
您可以使用二叉搜索树来确保数据已排序。 这将使其成为O(log N)操作。 然后,您可以一次遍历每个树一个项目,并在找到不等于条件时立即中断。 这也将为您提供额外的好处,即能够首先比较两棵树的大小,因为重复将被过滤掉。 我假设这些被视为集合,其中{“harry”,“harry”} == {“harry”)。
如果您正在计算重复项,那么先执行快速排序或合并排序,然后将比较操作作为O(N)操作。 你当然可以先比较大小,因为如果大小不同,两个枚举不能相等。 由于数据已排序,因此您遇到的第一个不相等的条件会将整个操作呈现为“不相等”。
@ cdhowie的答案很棒,但这里有一个很好的技巧,通过比较分解参数到IEnumerable
之前的值来声明.Count
的类型更好。 除了他的解决方案之外,只需将其添加到您的代码中:
上述就是C#学习教程:测试两个IEnumerable 是否具有相同频率的相同值分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public static bool UnsortedSequencesEqual(this IReadOnlyList first, IReadOnlyList second, IEqualityComparer comparer = null) { if (first.Count != second.Count) { return false; } return UnsortedSequencesEqual((IEnumerable )first, (IEnumerable )second, comparer); }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1025635.html