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)

29voto

codingatty Punkte 1688

Ich bin sehr spät zu der Partei und vielleicht etwas zu verpassen, aber wenn entweder gibt es keine doppelten Schlüssel oder, wie der OP sagt, "Im Falle einer Kollision, es spielt keine Rolle, welcher Wert in das Diktat gespeichert wird, solange es konsistent ist", was ist falsch mit diesem (Zusammenführen D2 in D1)?

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 übersehe. Dies ist, was ich in einigen Code verwenden, wo ich weiß, dass es keine doppelten Schlüssel sind. Ich bin noch in der Testphase, obwohl, so würde ich gerne jetzt wissen, wenn ich etwas übersehen, anstatt später herauszufinden.

23voto

ctrlalt313373 Punkte 3677
Dictionary<String, String> allTables = new Dictionary<String, String>();
allTables = tables1.Union(tables2).ToDictionary(pair => pair.Key, pair => pair.Value);

17voto

Option 1 : Dies hängt davon ab, was Sie wollen, wenn Sie sicher sind, dass Sie keine doppelten Schlüssel in beiden Wörterbüchern haben. als Sie tun könnten:

var result = dictionary1.Union(dictionary2).ToDictionary(k => k.Key, v => v.Value)

Anmerkung: Dies führt zu einer Fehlermeldung, wenn Sie doppelte Schlüssel in Wörterbüchern erhalten.

Option 2 : Wenn Sie doppelte Schlüssel haben können, dann müssen Sie doppelte Schlüssel mit der Verwendung von Where-Klausel zu behandeln.

var result = dictionary1.Union(dictionary2.Where(k => !dictionary1.ContainsKey(k.Key))).ToDictionary(k => k.Key, v => v.Value)

Anmerkung: Es wird keine doppelten Schlüssel erhalten. Wenn es einen doppelten Schlüssel gibt, wird er den Schlüssel von dictionary1 erhalten.

Option 3 : Wenn Sie ToLookup. verwenden möchten, erhalten Sie ein Lookup, das mehrere Werte pro Schlüssel haben kann. Sie können diese Abfrage in ein Wörterbuch umwandeln:

var result = dictionaries.SelectMany(dict => dict)
                         .ToLookup(pair => pair.Key, pair => pair.Value)
                         .ToDictionary(group => group.Key, group => group.First());

15voto

Ethan Reesor Punkte 1974

Bei mir funktioniert das wie folgt. Wenn es Duplikate gibt, wird der Wert von dictA verwendet.

public static IDictionary<TKey, TValue> Merge<TKey, TValue>(this IDictionary<TKey, TValue> dictA, IDictionary<TKey, TValue> dictB)
    where TValue : class
{
    return dictA.Keys.Union(dictB.Keys).ToDictionary(k => k, k => dictA.ContainsKey(k) ? dictA[k] : dictB[k]);
}

15voto

Andrew Harry Punkte 13617

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

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