639 Stimmen

Zusammenführen von Wörterbüchern in C#

Wie lassen sich 2 oder mehr Wörterbücher am besten zusammenführen ( Dictionary<T1,T2> ) in C#? (3.0-Funktionen wie LINQ sind in Ordnung).

Ich denke an eine Methodensignatur in der Art von:

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

o

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

EDIT: Ich habe eine coole Lösung von JaredPar und Jon Skeet, aber ich dachte an etwas, das mit doppelten Schlüsseln umgehen kann. Im Falle einer Kollision spielt es keine Rolle, welcher Wert im Diktat gespeichert wird, solange er konsistent ist.

238 Stimmen

Unabhängig davon, aber für jeden, der nur zwei Wörterbücher ohne Prüfung auf doppelte Schlüssel zusammenführen möchte, funktioniert dies sehr gut: dicA.Concat(dicB).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)

8 Stimmen

@Benjol Sie hätten dies im Antwortabschnitt hinzufügen können

8 Stimmen

Clojure's Zusammenführung in C#: dict1.Concat(dict2).GroupBy(p => p.Key).ToDictionary(g => g.Key, g => g.Last().Value)

1voto

gorillapower Punkte 442

Eine Version der Antwort von @user166390 mit einem Zusatz IEqualityComparer um die Groß- und Kleinschreibung beim Schlüsselvergleich nicht zu berücksichtigen.

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

1voto

idbrii Punkte 10063

Ich würde @orips einfache und nicht müllverursachende Lösung teilen, um eine in-place AddAll() zusätzlich zu Merge() um den einfachen Fall des Hinzufügens eines Wörterbuchs zu einem anderen zu behandeln.

using System.Collections.Generic;
...
public static Dictionary<TKey, TValue>
    AddAll<TKey,TValue>(Dictionary<TKey, TValue> dest, Dictionary<TKey, TValue> source)
{
    foreach (var x in source)
        dest[x.Key] = x.Value;
}

public static Dictionary<TKey, TValue>
    Merge<TKey,TValue>(IEnumerable<Dictionary<TKey, TValue>> dictionaries)
{
    var result = new Dictionary<TKey, TValue>();
    foreach (var dict in dictionaries)
        result.AddAll(dict);
    return result;
}

1voto

Sunday Punkte 474

Dies ist meine Lösung: Sie verhält sich wie die dict.update() Methode in Python.

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

0voto

mattylantz Punkte 265
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;
        }

0voto

Andrew Mikhailov Punkte 1009

Zusammenführen mit einer Erweiterungsmethode. Sie löst keine Ausnahme aus, wenn es doppelte Schlüssel gibt, sondern ersetzt diese Schlüssel durch Schlüssel aus dem zweiten Wörterbuch.

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

Verwendung:

Dictionary<string, string> merged = first.Merge(second);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X