[c#] Wörterbücher in C # zusammenführen



Answers

Ich würde es so machen:

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

Simpel und einfach. Laut diesem Blogpost ist es sogar schneller als die meisten Schleifen, da die zugrundeliegende Implementierung auf Elemente per Index statt auf Enumerator zugreift (siehe diese Antwort) .

Wenn Dubletten vorhanden sind, wird natürlich eine Ausnahme ausgelöst. Sie müssen also vor dem Zusammenführen prüfen.

Question

Was ist der beste Weg, um 2 oder mehr Wörterbücher ( Dictionary<T1,T2> ) in C # zusammenzuführen? (3,0 Funktionen wie LINQ sind in Ordnung).

Ich denke über eine Methodensignatur nach:

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

oder

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

EDIT: Eine coole Lösung von JaredPar und Jon Skeet, aber ich dachte an etwas, das doppelte Schlüssel behandelt. Im Falle einer Kollision ist es egal, welcher Wert im Diktat gespeichert wird, solange es konsistent ist.




Ich bin sehr spät zur Party und verpasse vielleicht etwas, aber wenn es entweder keine doppelten Schlüssel gibt oder, wie das OP sagt, "Im Falle einer Kollision ist es egal, welcher Wert im Diktat gespeichert wird, solange es ist konsistent, "was ist mit diesem falsch (D2 in D1 zusammenführen)?

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

Es scheint einfach genug, vielleicht zu einfach, ich frage mich, ob ich etwas verpasse. Dies ist, was ich in einem Code verwende, wo ich weiß, dass es keine doppelten Schlüssel gibt. Ich bin immer noch im Test, also würde ich gerne wissen, ob ich etwas übersehen habe, anstatt es später herauszufinden.




Ich weiß, das ist eine alte Frage, aber da wir jetzt LINQ haben, können Sie das in einer einzigen Zeile tun

Dictionary<T1,T2> merged;
Dictionary<T1,T2> mergee;
mergee.ToList().ForEach(kvp => merged.Add(kvp.Key, kvp.Value));

oder

mergee.ToList().ForEach(kvp => merged.Append(kvp));



oder :

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

Das Ergebnis ist eine Union, bei der doppelte Einträge "y" gewinnen.




Hier ist eine Hilfsfunktion, die ich verwende:

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



Basierend auf den obigen Antworten, aber Hinzufügen eines Func-Parameters, damit der Aufrufer die Duplikate verarbeiten kann:

public static Dictionary<TKey, TValue> Merge<TKey, TValue>(this IEnumerable<Dictionary<TKey, TValue>> dicts, 
                                                           Func<IGrouping<TKey, TValue>, TValue> resolveDuplicates)
{
    if (resolveDuplicates == null)
        resolveDuplicates = new Func<IGrouping<TKey, TValue>, TValue>(group => group.First());

    return dicts.SelectMany<Dictionary<TKey, TValue>, KeyValuePair<TKey, TValue>>(dict => dict)
                .ToLookup(pair => pair.Key, pair => pair.Value)
                .ToDictionary(group => group.Key, group => resolveDuplicates(group));
}



Zusammenführen mit einer Erweiterungsmethode. Es gibt keine Ausnahme aus, wenn doppelte Schlüssel vorhanden sind, 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);



Versuche Folgendes

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



Die triviale Lösung wäre:

using System.Collections.Generic;
...
public static Dictionary<TKey, TValue>
    Merge<TKey,TValue>(IEnumerable<Dictionary<TKey, TValue>> dictionaries)
{
    var result = new Dictionary<TKey, TValue>();
    foreach (var dict in dictionaries)
        foreach (var x in dict)
            result[x.Key] = x.Value;
    return result;
}



Related