Враховуючи ефективність пошуку ключових словників та видалень, оскільки вони є хеш-операціями, і вважаючи, що формулювання питання є найкращим способом, я вважаю, що нижче ідеально правильний підхід, а інші трохи складніші, 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);
}
}
АБО якщо ви працюєте в багатопотоковому додатку і ваш словник так чи інакше повинен бути безпечним для потоків, вам слід зробити це:
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);
}
}
Потім ви можете обернути це, щоб воно обробляло перелік словників. Незважаючи на те, ви дивитесь на ~ O (3n) (всі умови ідеальні), оскільки .Add()
воля зробить додаткову, непотрібну, але практично безкоштовну, Contains()
поза лаштунками. Я не думаю, що стає набагато краще.
Якщо ви хочете обмежити додаткові операції у великих колекціях, вам слід підбити підсумок Count
кожного словника, який ви збираєтеся об'єднати, і встановити ємність цільового словника до цього, що дозволяє уникнути подальшої вартості зміни розміру. Отже, кінцевий продукт - це щось подібне ...
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;
}
Зауважте, що я взяв на себе IList<T>
цей метод ... здебільшого тому, що якщо ви взяли на себе IEnumerable<T>
, ви відкрили собі кілька перелічень одного набору, що може бути дуже дорого, якщо ви отримали свою колекцію словників із відкладеного LINQ заява.
dicA.Concat(dicB).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)