Учитывая эффективность поиска и удаления ключевых слов в словаре, поскольку они являются операциями хэширования, и учитывая, что формулировка вопроса была наилучшим способом, я думаю, что приведенный ниже является совершенно корректным подходом, а остальные немного сложнее, ИМХО.
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)