Merging dictionaries in C#

前端 未结 26 984
温柔的废话
温柔的废话 2020-11-22 08:25

What\'s the best way to merge 2 or more dictionaries (Dictionary) in C#? (3.0 features like LINQ are fine).

I\'m thinking of a method signa

相关标签:
26条回答
  • 2020-11-22 08:58

    I would do it like this:

    dictionaryFrom.ToList().ForEach(x => dictionaryTo.Add(x.Key, x.Value));
    

    Simple and easy. According to this blog post it's even faster than most loops as its underlying implementation accesses elements by index rather than enumerator (see this answer).

    It will of course throw an exception if there are duplicates, so you'll have to check before merging.

    0 讨论(0)
  • 2020-11-22 08:58

    How about adding a params overload?

    Also, you should type them as IDictionary for maximum flexibility.

    public static IDictionary<TKey, TValue> Merge<TKey, TValue>(IEnumerable<IDictionary<TKey, TValue>> dictionaries)
    {
        // ...
    }
    
    public static IDictionary<TKey, TValue> Merge<TKey, TValue>(params IDictionary<TKey, TValue>[] dictionaries)
    {
        return Merge((IEnumerable<TKey, TValue>) dictionaries);
    }
    
    0 讨论(0)
  • 2020-11-22 08:58
    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;
            }
    
    0 讨论(0)
  • 2020-11-22 08:59

    I'm very late to the party and perhaps missing something, but if either there are no duplicate keys or, as the OP says, "In case of collision, it doesn't matter which value is saved to the dict as long as it's consistent," what's wrong with this one (merging D2 into D1)?

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

    It seems simple enough, maybe too simple, I wonder if I'm missing something. This is what I'm using in some code where I know there are no duplicate keys. I'm still in testing, though, so I'd love to know now if I'm overlooking something, instead of finding out later.

    0 讨论(0)
  • 2020-11-22 09:00

    A version from @user166390 answer with an added IEqualityComparer parameter to allow for case insensitive key comparison.

        public static T MergeLeft<T, K, V>(this T me, params Dictionary<K, V>[] others)
            where T : Dictionary<K, V>, new()
        {
            return me.MergeLeft(me.Comparer, others);
        }
    
        public static T MergeLeft<T, K, V>(this T me, IEqualityComparer<K> comparer, params Dictionary<K, V>[] others)
            where T : Dictionary<K, V>, new()
        {
            T newMap = Activator.CreateInstance(typeof(T), new object[] { comparer }) as T;
    
            foreach (Dictionary<K, V> src in 
                (new List<Dictionary<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;
        }
    
    0 讨论(0)
  • 2020-11-22 09:03

    Here is a helper function I use:

    using System.Collections.Generic;
    namespace HelperMethods
    {
        public static class MergeDictionaries
        {
            public static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second)
            {
                if (second == null || first == null) return;
                foreach (var item in second) 
                    if (!first.ContainsKey(item.Key)) 
                        first.Add(item.Key, item.Value);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题