查明两个ICollection <t>集合是否包含相同对象的最快方法</t>

时间:2008-11-21 11:24:35

标签: c# performance collections c#-2.0 equality

找出两个ICollection<T>集合是否包含完全相同的条目的最快方法是什么?蛮力很明显,我想知道是否有更优雅的方法。

我们正在使用C#2.0,所以请尽可能没有扩展方法!

编辑:对于有序和无序集合,答案都很有趣,并且希望每个集合都有所不同。

7 个答案:

答案 0 :(得分:4)

使用C5

http://www.itu.dk/research/c5/

ContainsAll

  

“检查是否所有项目   提供的收藏品在这个包里   (计算多重性)。
     该   要查找的项目。
  
  如果所有项目都是真的   找到。“

[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;
}

答案 1 :(得分:3)

首先比较集合的。 Count ,如果它们具有相同的计数,则对所有元素进行强力比较。最糟糕的情况是O(n)。在这种情况下,元素的顺序必须相同。

第二种情况,订单不一样,你需要使用字典来存储集合中找到的元素数量:这是一个可能的算法

  • 比较集合计数:如果它们不同则返回false
  • 迭代第一个集合
    • 如果词典中不存在项目,则使用Key = Item,Value = 1(计数)
    • 添加和输入
    • 如果item存在,则递增字典中item的计数;
  • 迭代第二个集合
    • 如果item不在字典中,则返回false
    • 如果项目在项目的字典减量计数中
      • 如果count == 0则删除项目;
  • return Dictionary.Count == 0;

答案 2 :(得分:3)

对于有序集合,您可以使用SequenceEqual()定义的System.Linq.Enumerable扩展方法:

if (firstCollection.SequenceEqual(secondCollection))

答案 3 :(得分:2)

您的意思是相同的条目或相同的条目?

无论如何,假设您想要比较它们是否包含相同顺序的相同条目,“暴力”实际上是您在C#2.0中唯一的选择。我知道你的意思是非优雅,但如果原子比较本身是O(1),整个过程应该是O(N),这不是 坏。

答案 4 :(得分:1)

如果条目需要处于相同的顺序(除了相同),那么我建议 - 作为优化 - 您同时迭代两个集合并比较每个集合中的当前条目。否则,蛮力是要走的路。

哦,还有另一个建议 - 你可以为集合类重写Equals并在那里实现相等的东西(取决于你的项目)。

答案 5 :(得分:1)

同样,使用具有两组的C5库,您可以使用:

C5.ICollection<T> set1 = C5.ICollection<T> ();
C5.ICollection<T> set2 = C5.ICollecton<T> ();
if (set1.UnsequencedEquals (set2)) {
  // Do something
}

C5库包含一个启发式实际上首先测试两个集合的未序列哈希码(参见C5.ICollection<T>.GetUnsequencedHashCode()),这样如果两个集合的哈希码不相等,则不需要迭代每个项目都要测试是否平等。

另外值得注意的是C5.ICollection<T>继承自System.Collections.Generic.ICollection<T>,因此您可以在使用.NET接口的同时使用C5实现(尽管您可以通过.NET的吝啬接口访问较少的功能)。

答案 6 :(得分:0)

蛮力需要O(n) - 比较所有元素(假设它们已被排序),我认为这是你能做的最好的 - 除非数据的某些属性使其更容易。

我想对于未排序的情况,其O(n * n)。

在这种情况下,我认为基于merge sort的解决方案可能有所帮助。

例如,您是否可以重新建模,以便只有一个集合?或者3个集合,一个用于集合A中的集合,一个仅用于B和两个集合 - 所以如果A只和B只是空 - 那么它们是相同的...我可能会完全错误的切线这里...