将具有重复键的 2 个字典与 linq 合并

Posted

技术标签:

【中文标题】将具有重复键的 2 个字典与 linq 合并【英文标题】:Merging 2 dictionaries having duplicate keys with linq 【发布时间】:2011-10-17 16:56:40 【问题描述】:

如何合并IDictionary<Guid, MyObject>的2个字典,其中MyObject是一个类实例?

IDictionary<Guid, MyObject> d1 = new Dictionary<Guid, MyObject>();
d1.Add(guid1, m1);
d1.Add(guid2, m2);
d1.Add(guid3, m3);
IDictionary<Guid, MyObject> d2 = new Dictionary<Guid, MyObject>();
d2.Add(guid2, m2);
d2.Add(guid3, m3);
d2.Add(guid4, m4);
IDictionary<Guid, MyObject> d3 = d1.Union(d2) ???

d3 中有以下条目:

guid1,m1
guid2,m2
guid3,m3
guid4,m4

【问题讨论】:

与***.com/questions/294138/merging-dictionaries-in-c重复 对不起,我在那里找不到我的解决方案 Combine two Dictionaries with linq 的可能重复项;比另一个更精确的重复 重复Combine two Dictionaries with LINQ 【参考方案1】:
d1.Concat(d2.Where( x=> !d1.Keys.Contains(x.Key)));

【讨论】:

非常感谢,虽然领先处理连接集,但这是正确的方法 @Eric 这看起来是个不错的解决方案。但是,如果我有IEnuemrable&lt;Dictionary&lt;Guid, MyObject&gt;&gt; 集合,我该如何匹配项目? 我发现当 d1 较小(2 条记录)而 d2 较大(100,000 条记录)时联合速度更快。【参考方案2】:

d1.Union(d2).GroupBy (kvp =&gt; kvp.Key).ToDictionary(kvp =&gt; kvp.Key, kvp =&gt; kvp.First().Value); 解决问题。

IDictionary<Guid, MyObject> d1 = new Dictionary<Guid, MyObject>();
d1.Add(guid1, m1);
d1.Add(guid2, m2);
d1.Add(guid3, m3);
IDictionary<Guid, MyObject> d2 = new Dictionary<Guid, MyObject>();
d2.Add(guid2, m2);
d2.Add(guid3, m3);
d2.Add(guid4, m4);
IDictionary<Guid, MyObject> d3 = 
   d1.Union(d2).GroupBy (kvp => kvp.Key)
       .ToDictionary (kvp => kvp.Key, kvp => kvp.First ().Value);

【讨论】:

谢谢,但我试过了,Union 导致异常,“已添加具有相同密钥的项目” 我修好了。 ` IDictionary d3 = d1.Union(d2).GroupBy (kvp => kvp.Key) .ToDictionary (kvp => kvp.Key, kvp => kvp.First ().Value); ` 非常感谢,这行得通,那行如何避免重复键?这比d1.Concat(d2.Where(x =&gt; !d1.Keys.Contains(x.Key))) 快吗? 我测试过,使用秒表,使用 Concat 快 3 倍,所以不要使用 Union【参考方案3】:

如果你有重复键,那么你必须使用 where 子句来处理重复键。

var result = d1.Union(d2.Where(k => !d1.ContainsKey(k.Key))).ToDictionary(k => k.Key, v => v.Value)

注意:它不会得到重复的密钥。如果有任何重复的密钥,它将获得 d1 的密钥。

【讨论】:

【参考方案4】:

你可以试试

d1.Concat(d2).Distinct(kv => kv.Key).ToDictionary(kv => kv.Key, kv => kv.Value)

concat 的结果利用了字典是IEnumerable&lt;KeyvaluePair&lt;Guid,MyObject&gt;&gt;这一事实

因为我没有编译器,所以我刚刚检查了 Distinct 不能只接受一个选择要比较的属性的 lambda。但是它可以接受 EqualityComparer。我在项目中经常使用的是通用相等比较器,它允许传入定义相等操作的 lambda。

【讨论】:

【参考方案5】:

当不存在重复键时,以下适用于 2 个(或更多)字典:

var dictionaries = new []  d1, d2 ;
var result = dictionaries.SelectMany(dict => dict)
                     .ToDictionary(pair => pair.Key, pair => pair.Value);

【讨论】:

【参考方案6】:

联合看起来不错: http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#union1

【讨论】:

以上是关于将具有重复键的 2 个字典与 linq 合并的主要内容,如果未能解决你的问题,请参考以下文章

如何将在多行中具有相同键的字典转换为数据框[重复]

具有重复键的字典 [重复]

具有相同键的多个条目的字典[重复]

LINQ合并2个列表,保持顺序和来源[重复]

仅包含每个重复项中的第一个的 Linq 键

服务器与本地机器上dict键的随机顺序[重复]