Biorąc pod uwagę wydajność wyszukiwania i usuwania kluczy słownikowych, ponieważ są to operacje haszujące, i biorąc pod uwagę, że sformułowanie pytania było najlepszym sposobem, myślę, że poniżej jest całkowicie poprawne podejście, a pozostałe są nieco zbyt skomplikowane, IMHO.
public static void MergeOverwrite<T1, T2>(this IDictionary<T1, T2> dictionary, IDictionary<T1, T2> newElements)
{
if (newElements == null) return;
foreach (var e in newElements)
{
dictionary.Remove(e.Key); //or if you don't want to overwrite do (if !.Contains()
dictionary.Add(e);
}
}
LUB jeśli pracujesz w aplikacji wielowątkowej, a słownik i tak musi być bezpieczny dla wątków, powinieneś to zrobić:
public static void MergeOverwrite<T1, T2>(this ConcurrentDictionary<T1, T2> dictionary, IDictionary<T1, T2> newElements)
{
if (newElements == null || newElements.Count == 0) return;
foreach (var ne in newElements)
{
dictionary.AddOrUpdate(ne.Key, ne.Value, (key, value) => value);
}
}
Następnie możesz to zawinąć, aby obsłużyć wyliczenie słowników. Niezależnie od tego, patrzysz na ~ O (3n) (wszystkie warunki są idealne), ponieważ .Add()
zrobi to dodatkowe, niepotrzebne, ale praktycznie bezpłatne,Contains()
za kulisami. Nie sądzę, żeby było znacznie lepiej.
Jeśli chcesz ograniczyć dodatkowe operacje na dużych kolekcjach, powinieneś podsumować Count
każdy słownik, który zamierzasz scalić, i ustawić pojemność słownika docelowego do tego, co pozwala uniknąć późniejszych kosztów zmiany rozmiaru. Tak więc produkt końcowy jest taki ...
public static IDictionary<T1, T2> MergeAllOverwrite<T1, T2>(IList<IDictionary<T1, T2>> allDictionaries)
{
var initSize = allDictionaries.Sum(d => d.Count);
var resultDictionary = new Dictionary<T1, T2>(initSize);
allDictionaries.ForEach(resultDictionary.MergeOverwrite);
return resultDictionary;
}
Zauważ, że wybrałem IList<T>
tę metodę ... głównie dlatego, że jeśli ją wprowadziłeś IEnumerable<T>
, otworzyłeś się na wiele wyliczeń tego samego zestawu, co może być bardzo kosztowne, jeśli masz swoją kolekcję słowników z odroczonego LINQ komunikat.
dicA.Concat(dicB).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)