在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);
关于重复键的处理:在发生冲突的情况下,保存到字典中的值并不重要,只要它是一致的。
使用equalitycompararer进行合并,它将项目映射到不同的值/类型进行比较。这里我们将从KeyValuePair(枚举字典时的项类型)映射到Key。
public class MappedEqualityComparer<T,U> : EqualityComparer<T>
{
Func<T,U> _map;
public MappedEqualityComparer(Func<T,U> map)
{
_map = map;
}
public override bool Equals(T x, T y)
{
return EqualityComparer<U>.Default.Equals(_map(x), _map(y));
}
public override int GetHashCode(T obj)
{
return _map(obj).GetHashCode();
}
}
用法:
// if dictA and dictB are of type Dictionary<int,string>
var dict = dictA.Concat(dictB)
.Distinct(new MappedEqualityComparer<KeyValuePair<int,string>,int>(item => item.Key))
.ToDictionary(item => item.Key, item=> item.Value);
与之前没有LINQ的情况下再次简化,如果存在则使用bool默认值非破坏性合并,如果为true则完全覆盖,而不是使用enum。它仍然适合我自己的需要,而不需要任何花哨的代码:
using System.Collections.Generic;
using System.Linq;
public static partial class Extensions
{
public static void Merge<K, V>(this IDictionary<K, V> target,
IDictionary<K, V> source,
bool overwrite = false)
{
foreach (KeyValuePair _ in source)
if (overwrite || !target.ContainsKey(_.Key))
target[_.Key] = _.Value;
}
}
注意,如果你使用一个名为“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" }
};