【问题标题】:Comparing two sets for new and missing keys比较两组新键和缺失键
【发布时间】:2010-09-19 15:25:26
【问题描述】:

在比较 C# 中的两个键值字典集:集合 A 和集合 B 时,枚举集合 A 中存在但集合 B 中缺少的键的最佳方法是什么,反之亦然?

例如:

A = { 1, 2, 5 }
B = { 2, 3, 5 }

比较 B 和 A,缺少键 = { 1 } 和新键 = { 3 }。

使用Dictionary<...,...> 对象,可以枚举B 中的所有值并使用A.ContainsKey(key); 对集合A 进行测试,但感觉应该有更好的方法可能涉及排序集?

【问题讨论】:

  • 可能有一个微不足道的答案,但我希望它对大型集合或频繁更改具有高性能。

标签: c# dictionary comparison set


【解决方案1】:

我知道两种用于设置差异的内置方法。

1) Enumerable.Except

通过使用默认相等比较器比较值来产生两个序列的集合差。

例子:

IEnumerable<int> a = new int[] { 1, 2, 5 };
IEnumerable<int> b = new int[] { 2, 3, 5 };

foreach (int x in a.Except(b))
{
    Console.WriteLine(x);  // prints "1"
}

2a) HashSet<T>.ExceptWith

从当前 HashSet 对象中移除指定集合中的所有元素。

HashSet<int> a = new HashSet<int> { 1, 2, 5 };
HashSet<int> b = new HashSet<int> { 2, 3, 5 };

a.ExceptWith(b);

foreach (int x in a)
{
    Console.WriteLine(x);  // prints "1"
}

2b)HashSet<T>.SymmetricExceptWith

修改当前的 HashSet 对象以仅包含存在于该对象或指定集合中的元素,但不能同时包含两者。

HashSet<int> a = new HashSet<int> { 1, 2, 5 };
HashSet<int> b = new HashSet<int> { 2, 3, 5 };

a.SymmetricExceptWith(b);

foreach (int x in a)
{
    Console.WriteLine(x);  // prints "1" and "3"
}

如果您需要更高性能的东西,您可能需要推出自己的集合类型。

【讨论】:

  • @Steve Guidi - 您如何使用 HashSet 处理键值数据?
【解决方案2】:

使用SortedDictionary:逻辑是A.Except(A.Intersect(B))

在您确定这是您的数据集的问题之前,不要过分担心性能。

【讨论】:

  • +1 优化正确的程序比纠正优化的程序更容易:)
【解决方案3】:

您可以使用Except 方法。

Dictionary<string, string> dic1 = new Dictionary<string, string>() { { "rabbit", "hat" }, { "frog", "pond" }, { "cat", "house" } };
Dictionary<string, string> dic2 = new Dictionary<string, string>() { { "rabbit", "hat" }, { "dog", "house"}, {"cat", "garden"}};

    var uniqueKeys = dic1.Keys.Except(dic2.Keys);

    foreach (var item in uniqueKeys)
    {
        Console.WriteLine(item);
    }
【解决方案4】:

所以这里有几个可行的答案。但您最初的问题最好分两部分解决:

Q) 当比较 C# 中的两个键值字典集:集合 A 和集合 B 时,枚举集合 A 中存在但集合 B 中缺少的键的最佳方法是什么,反之亦然?使用 Dictionary<...> 对象,可以枚举 B 中的所有值并使用 A.ContainsKey(key);, ... 对集合 A 进行测试。

如果您从两本词典开始,这可能是最好的方法。做任何其他事情都需要从两组中创建密钥的副本,从而使大多数替代方案更加昂贵。

Q) ...但感觉应该有更好的方法可能涉及排序集?

是的,这可以通过排序列表轻松完成。创建两个使用 BinarySearch 排序的列表插入,然后在搜索集 2 等时遍历集 1。

请参阅此 SetList 补和减操作: http://csharptest.net/browse/src/Library/Collections/SetList.cs#234

【讨论】:

    猜你喜欢
    • 2015-12-17
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    相关资源
    最近更新 更多