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

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


当前回答

public static IDictionary<K, V> AddRange<K, V>(this IDictionary<K, V> one, IDictionary<K, V> two)
        {
            foreach (var kvp in two)
            {
                if (one.ContainsKey(kvp.Key))
                    one[kvp.Key] = two[kvp.Key];
                else
                    one.Add(kvp.Key, kvp.Value);
            }
            return one;
        }

其他回答

using System.Collections.Generic;
using System.Linq;

public static class DictionaryExtensions
{
    public enum MergeKind { SkipDuplicates, OverwriteDuplicates }
    public static void Merge<K, V>(this IDictionary<K, V> target, IDictionary<K, V> source, MergeKind kind = MergeKind.SkipDuplicates) =>
        source.ToList().ForEach(_ => { if (kind == MergeKind.OverwriteDuplicates || !target.ContainsKey(_.Key)) target[_.Key] = _.Value; });
}

你可以跳过/忽略(默认)或覆盖副本:如果你对Linq性能不过分挑剔,而是像我一样喜欢简洁的可维护代码:在这种情况下,你可以删除默认的MergeKind。skipduplicate用于强制调用者进行选择,并使开发人员知道结果将是什么!

使用扩展方法合并。当存在重复的键时,它不会抛出异常,而是用第二个字典中的键替换这些键。

internal static class DictionaryExtensions
{
    public static Dictionary<T1, T2> Merge<T1, T2>(this Dictionary<T1, T2> first, Dictionary<T1, T2> second)
    {
        if (first == null) throw new ArgumentNullException("first");
        if (second == null) throw new ArgumentNullException("second");

        var merged = new Dictionary<T1, T2>();
        first.ToList().ForEach(kv => merged[kv.Key] = kv.Value);
        second.ToList().ForEach(kv => merged[kv.Key] = kv.Value);

        return merged;
    }
}

用法:

Dictionary<string, string> merged = first.Merge(second);
Dictionary<String, String> allTables = new Dictionary<String, String>();
allTables = tables1.Union(tables2).ToDictionary(pair => pair.Key, pair => pair.Value);

这是我的解决方案:它的行为类似于python中的dict.update()方法。

public static class DictionaryExtensions
{
    public static void Update<K,V>(this IDictionary<K, V> me, IDictionary<K, V> other)
    {
        foreach (var x in other)
        {
            me[x.Key] = x.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;
    }