找出两个ICollection<T>
集合是否包含完全相同的条目的最快方法是什么?蛮力很清楚,我想知道是否有更优雅的方法。
我们使用的是 C# 2.0,所以请尽可能不要扩展方法!
编辑:对于有序和无序的集合,答案都会很有趣,并且希望每个集合都不同。
找出两个ICollection<T>
集合是否包含完全相同的条目的最快方法是什么?蛮力很清楚,我想知道是否有更优雅的方法。
我们使用的是 C# 2.0,所以请尽可能不要扩展方法!
编辑:对于有序和无序的集合,答案都会很有趣,并且希望每个集合都不同。
使用 C5
http://www.itu.dk/research/c5/
" 检查提供的集合中的所有项目是否都在这个包中
(计算多重性)。
要查找的项目。
如果找到所有项目,则为真。"
[Tested]
public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
{
HashBag<T> res = new HashBag<T>(itemequalityComparer);
foreach (T item in items)
if (res.ContainsCount(item) < ContainsCount(item))
res.Add(item);
else
return false;
return true;
}
首先比较一下。如果集合的计数相同,则对所有元素进行蛮力比较。最坏的情况是 O(n)。这是在元素的顺序需要相同的情况下。
顺序不一样的第二种情况,您需要使用字典来存储在集合中找到的元素的计数:这是一个可能的算法
对于有序集合,您可以使用SequenceEqual()
定义的扩展方法System.Linq.Enumerable
:
if (firstCollection.SequenceEqual(secondCollection))
您的意思是相同的条目或相同顺序的相同条目?
无论如何,假设您想比较它们是否以相同的顺序包含相同的条目,“蛮力”实际上是您在 C# 2.0 中的唯一选择。我知道你说的非优雅是什么意思,但是如果原子比较本身是 O(1),那么整个过程应该是 O(N),这还不错。
如果条目需要以相同的顺序排列(除了相同),那么我建议 - 作为一种优化 - 您同时迭代两个集合并比较每个集合中的当前条目。否则,蛮力就是要走的路。
哦,还有另一个建议——你可以为集合类重写 Equals 并在其中实现相等的东西(不过取决于你的项目)。
同样,使用具有两组的 C5 库,您可以使用:
C5.ICollection<T> set1 = C5.ICollection<T> (); C5.ICollection<T> set2 = C5.ICollection<T> (); if (set1.UnsequencedEquals (set2)) { // 做点什么 }
C5 库包含一个启发式算法,它首先实际测试两组的未排序哈希码(请参阅 参考资料C5.ICollection<T>.GetUnsequencedHashCode()
),这样如果两组的哈希码不相等,它就不需要遍历每个项目来测试是否相等。
您还需要注意的是,它C5.ICollection<T>
继承自System.Collections.Generic.ICollection<T>
,因此您可以在仍然使用 .NET 接口的同时使用 C5 实现(尽管您可以通过 .NET 的吝啬接口访问较少的功能)。
蛮力需要 O(n) - 比较所有元素(假设它们已排序),我认为这是你能做的最好的 - 除非数据的某些属性使它更容易。
我猜对于未排序的情况,它的 O(n*n)。
在这种情况下,我认为基于合并排序的解决方案可能会有所帮助。
例如,您能否对其进行重新建模以使其只有一个系列?或 3 个集合,一个仅用于集合 A,一个仅用于 B,并且两者都用于 - 所以如果 A only 和 B only 是空的 - 那么它们是相同的......我可能完全走错了切线这里...