【问题标题】:Merging dictionaries in key level and then in value level在键级别合并字典,然后在值级别
【发布时间】:2010-09-03 09:06:20
【问题描述】:

我有两本类似的字典

Dictionary<String, String> one = new Dictionary<string, string>
{
    { "A", "1" },
    { "B", "2" },
    { "C", "3" },
    { "D", "4" },
    { "E", "5" },
    { "F", "6" },
    { "G", "7" },
    { "H", "8" }
};

Dictionary<String, String> two = new Dictionary<string, string>
{
    { "A", "1" },
    { "B", "2" },
    { "C", "3" },
    { "E", "4" },
    { "F", "4" },
    { "I", "6" },
    { "J", "10" },
    { "K", "11" }
};

我需要在键级别和值级别合并两个字典,并将结果字典添加到新字典three,结果字典不应该有相同的键或相同的值,在这种情况下结果字典就像

Dictionary<String, String> three = new Dictionary<string, string>
{
    { "A", "1" },
    { "B", "2" },
    { "C", "3" },
    { "D", "4" },
    { "E", "5" },
    { "F", "6" },
    { "G", "7" },
    { "H", "8" },
    { "J", "10" },
    { "K", "11" }
};

现在我正在使用喜欢

  1. 联合两个字典中的所有键
  2. 使用新键创建新字典
  3. 删除重复值(相同值)

编辑:如果两个字典具有相同的键值对,那么我需要存储第一个字典中的键值对。

有没有办法使用 LINQ 来做到这一点? 提前致谢

【问题讨论】:

  • 当两个字典中的键匹配时,您希望将值存储在第一个字典中,就像对 F, 6 所做的那样?
  • 是的。如果两个字典具有相同的键值对,那么我需要存储第一个字典中的键值对
  • 您需要更精确地指定冲突解决规则。

标签: c# linq dictionary


【解决方案1】:

一个选项,使用字典是一系列键/值对的事实:

var dictionary = dictionary1.Concat(dictionary2)
                            .ToLookup(pair => pair.Key, pair => pair.Value)
                            .ToDictionary(x => x.Key, x => x.First());

诚然,这并不是非常有效(因为它实际上建立了两次哈希表),但我相信它会起作用。

【讨论】:

  • @Jon Skeet:谢谢,我需要从“字典”中删除重复的值。正如我所提到的,结果字典不应包含相同的键或相同的值
  • @Pramodh:在不同的地方查看我的答案
  • 乔恩,你能描述一下ToLookup()你用过什么吗?
  • @abatishchev:它允许多个条目具有相同的键。然后我们在构建字典时只取第一个值。
  • @Pramodh:“相同的键或相同的值”到底是什么意思?请举一个具体的例子说明我的代码不能满足你想要发生的事情。
【解决方案2】:

仅 linq 的方法是将两个字典连接起来,并将生成的键/值序列折叠成一个结果。这将覆盖 dict2 中的任何键的值,这些键也在 dict1 中:

var dict3 = dict2.Concat(dict1)
    .Aggregate(new Dictionary<string, string>(), (d, kvp) => {
        d[kvp.Key] = kvp.Value;
        return d;
    });

【讨论】:

    【解决方案3】:
    class StringKeyValuePairEqualityComparer : IEqualityComparer<KeyValuePair<string, string>>
    {
        public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
        {
            return x.Key == y.Key;
        }
    
        public int GetHashCode(KeyValuePair<string, string> obj)
        {
            return obj.Key.GetHashCode();
        }
    }
    
    var three = Enumerable.Concat(one, two)
                    .Distinct(new StringKeyValuePairEqualityComparer())
                    .ToDictionary(p => p.Key, p => p.Value);
    
    int count = three.Keys.Count; // 11
    

    【讨论】:

      【解决方案4】:
      var three = new Dictionary<string, string>();
      foreach(var kvp in two.Concat(one))
        three[kvp.Key] = kvp.Value;
      

      这非常有效,但我不确定这是否是您想要的输出;问题陈述不够清楚。

      编辑:如果您想随后从three 中删除重复的

      var keysWithDuplicateValues = three.ToLookup(kvp => kvp.Value, kvp => kvp.Key)
                                         .SelectMany(group => group.Skip(1))
                                         .ToList();
      
      foreach(var key in keysWithDuplicateValues)
         three.Remove(key);   
      

      请注意,这比一开始就急切地删除重复键重复值要好,因为某些冲突可能会自动解决。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-20
        • 2018-03-02
        • 2021-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-25
        • 2014-07-27
        相关资源
        最近更新 更多