在c#中合并2个或更多字典(Dictionary<TKey, TValue>)的最佳方法是什么?
(像LINQ这样的3.0特性就可以了)。
我正在考虑一个方法签名,如下所示:
public static Dictionary<TKey,TValue>
Merge<TKey,TValue>(Dictionary<TKey,TValue>[] dictionaries);
or
public static Dictionary<TKey,TValue>
Merge<TKey,TValue>(IEnumerable<Dictionary<TKey,TValue>> dictionaries);
关于重复键的处理:在发生冲突的情况下,保存到字典中的值并不重要,只要它是一致的。
注意,如果你使用一个名为“Add”的扩展方法,你可以使用集合初始化器来组合尽可能多的字典,就像这样:
public static void Add<K, V>(this Dictionary<K, V> d, Dictionary<K, V> other) {
foreach (var kvp in other)
{
if (!d.ContainsKey(kvp.Key))
{
d.Add(kvp.Key, kvp.Value);
}
}
}
var s0 = new Dictionary<string, string> {
{ "A", "X"}
};
var s1 = new Dictionary<string, string> {
{ "A", "X" },
{ "B", "Y" }
};
// Combine as many dictionaries and key pairs as needed
var a = new Dictionary<string, string> {
s0, s1, s0, s1, s1, { "C", "Z" }
};
这在一定程度上取决于如果遇到重复项,你希望发生什么。例如,你可以这样做:
var result = dictionaries.SelectMany(dict => dict)
.ToDictionary(pair => pair.Key, pair => pair.Value);
如果您获得任何重复的键,将抛出异常。
编辑:如果你使用ToLookup,那么你会得到一个查找,每个键可以有多个值。然后你可以把它转换成一个字典:
var result = dictionaries.SelectMany(dict => dict)
.ToLookup(pair => pair.Key, pair => pair.Value)
.ToDictionary(group => group.Key, group => group.First());
这有点难看——而且效率很低——但从代码的角度来说,这是最快的方法。(不得不承认,我还没有测试过它。)
当然,您也可以编写自己的ToDictionary2扩展方法(有一个更好的名字,但我现在没有时间去想)——这并不难做到,只是覆盖(或忽略)重复的键。重要的一点(在我看来)是使用SelectMany,并意识到字典支持键/值对的迭代。
试试
namespace Extensions
{
public static class DictionaryExtensions
{
public static Dictionary<T, Y> MergeWith<T, Y>(this Dictionary<T, Y> dictA,
Dictionary<T, Y> dictB)
{
foreach (var item in dictB)
{
if (dictA.ContainsKey(item.Key))
dictA[item.Key] = item.Value;
else
dictA.Add(item.Key, item.Value);
}
return dictA;
}
}
}
当你想合并两个字典时
var d1 = new Dictionary<string, string>();
var d2 = new Dictionary<string, string>();
d1.MergeWith(d2);
我将分解@orip的简单而非垃圾的创建解决方案,以提供除了Merge()之外的一个适当的AddAll()来处理将一个字典添加到另一个字典的简单情况。
using System.Collections.Generic;
...
public static Dictionary<TKey, TValue>
AddAll<TKey,TValue>(Dictionary<TKey, TValue> dest, Dictionary<TKey, TValue> source)
{
foreach (var x in source)
dest[x.Key] = x.Value;
}
public static Dictionary<TKey, TValue>
Merge<TKey,TValue>(IEnumerable<Dictionary<TKey, TValue>> dictionaries)
{
var result = new Dictionary<TKey, TValue>();
foreach (var dict in dictionaries)
result.AddAll(dict);
return result;
}