Слияние словарей в C # - PullRequest
       81

Слияние словарей в C #

433 голосов
/ 16 ноября 2008

Как лучше всего объединить 2 или более словарей (Dictionary<T1,T2>) в C #? (3.0 функции, такие как LINQ, в порядке).

Я думаю о сигнатуре метода в соответствии с:

public static Dictionary<TKey,TValue>
                 Merge<TKey,TValue>(Dictionary<TKey,TValue>[] dictionaries);

или

public static Dictionary<TKey,TValue>
                 Merge<TKey,TValue>(IEnumerable<Dictionary<TKey,TValue>> dictionaries);

РЕДАКТИРОВАТЬ: Получил классное решение от JaredPar и Jon Skeet, но я думал о чем-то, что обрабатывает дубликаты ключей. В случае коллизии не имеет значения, какое значение сохранено в dict, если оно согласованно.

Ответы [ 23 ]

0 голосов
/ 11 октября 2017

или:

public static IDictionary<TKey, TValue> Merge<TKey, TValue>( IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y)
    {
        return x
            .Except(x.Join(y, z => z.Key, z => z.Key, (a, b) => a))
            .Concat(y)
            .ToDictionary(z => z.Key, z => z.Value);
    }

результатом является объединение, в котором для повторяющихся записей "y" выигрывает.

0 голосов
/ 15 мая 2019

Версия от @ user166390 ответа с добавленным параметром IEqualityComparer, позволяющим проводить сравнение ключей без учета регистра.

    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 голосов
/ 30 мая 2014

Слияние с использованием EqualityComparer, которое сопоставляет элементы для сравнения с другим значением / типом. Здесь мы отобразим от 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...