在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);

关于重复键的处理:在发生冲突的情况下,保存到字典中的值并不重要,只要它是一致的。


当前回答

我来晚了,可能错过了一些东西,但如果没有重复的键,或者正如OP所说的那样,“如果发生碰撞,只要值是一致的,保存到字典中的值并不重要”,那么这个(将D2合并到D1)有什么问题?

foreach (KeyValuePair<string,int> item in D2)
{
    D1[item.Key] = item.Value;
}

这看起来很简单,也许太简单了,我想知道我是否遗漏了什么。这是我在一些代码中使用的,我知道没有重复的键。不过,我仍在测试中,所以我现在就想知道我是否忽略了一些东西,而不是以后才发现。

其他回答

Dictionary<String, String> allTables = new Dictionary<String, String>();
allTables = tables1.Union(tables2).ToDictionary(pair => pair.Key, pair => pair.Value);

试试下面的方法

static Dictionary<TKey, TValue>
    Merge<TKey, TValue>(this IEnumerable<Dictionary<TKey, TValue>> enumerable)
{
    return enumerable.SelectMany(x => x).ToDictionary(x => x.Key, y => y.Value);
}

使用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);

@Tim:应该是注释,但是注释不允许代码编辑。

Dictionary<string, string> t1 = new Dictionary<string, string>();
t1.Add("a", "aaa");
Dictionary<string, string> t2 = new Dictionary<string, string>();
t2.Add("b", "bee");
Dictionary<string, string> t3 = new Dictionary<string, string>();
t3.Add("c", "cee");
t3.Add("d", "dee");
t3.Add("b", "bee");
Dictionary<string, string> merged = t1.MergeLeft(t2, t2, t3);

注意:我应用了@ANeves对@Andrew Orsich的解决方案的修改,所以mergleft现在看起来像这样:

public static Dictionary<K, V> MergeLeft<K, V>(this Dictionary<K, V> me, params IDictionary<K, V>[] others)
    {
        var newMap = new Dictionary<K, V>(me, me.Comparer);
        foreach (IDictionary<K, V> src in
            (new List<IDictionary<K, V>> { me }).Concat(others))
        {
            // ^-- echk. Not quite there type-system.
            foreach (KeyValuePair<K, V> p in src)
            {
                newMap[p.Key] = p.Value;
            }
        }
        return newMap;
    }

试试

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);