Я поместил в список https://pypi.python.org/pypi/linked_list_mod/
класс списка с одиночным соединением Python 2.x и 3.x] Он тестируется с CPython 2.7, CPython 3.4, Pypy 2.3.1, Pypy3 2.3.1 и Jython 2.7b2 и поставляется с красивым автоматизированным набором тестов.
Он также включает классы LIFO и FIFO.
Они не являются неизменными, хотя.
Это частично зависит от того, что Вы хотите произойти при столкновении с дубликатами. Например, Вы могли сделать:
var result = dictionaries.SelectMany(dict => dict)
.ToDictionary(pair => pair.Key, pair => pair.Value);
, Который аварийно завершится, если Вы получите кого-либо, делают дубликаты ключа.
РЕДАКТИРОВАНИЕ: при использовании ToLookup тогда, Вы получите поиск, который может иметь несколько значений на ключ. Вы могли затем преобразовывать это в словарь:
var result = dictionaries.SelectMany(dict => dict)
.ToLookup(pair => pair.Key, pair => pair.Value)
.ToDictionary(group => group.Key, group => group.First());
Это немного ужасно - и неэффективно - но это - самый быстрый способ сделать это с точки зрения кода. (Я не протестировал его по общему признанию.)
Вы могли записать свой собственный дополнительный метод ToDictionary2, конечно (с лучшим именем, но у меня нет времени для размышления о том теперь) - не ужасно трудно сделать, просто перезаписывание (или игнорирование) делают дубликаты ключа. Важный бит (по моему мнению) использует SelectMany и понимает, что словарь поддерживает повторение по своим парам ключ/значение.
@Tim: должен быть комментарий, но комментарии не позволяют редактировать код.
Dictionary<string, string> t1 = new Dictionary<string, string>();
t1.Add("a", "aaa");
Dictionary<string, string> t2 = new Dictionary<string, string>();
t2.Add("b", "bee");
Dictionary<string, string> t3 = new Dictionary<string, string>();
t3.Add("c", "cee");
t3.Add("d", "dee");
t3.Add("b", "bee");
Dictionary<string, string> merged = t1.MergeLeft(t2, t2, t3);
Примечание: я применил модификацию @ANeves к решению @Andrew Orsich, поэтому MergeLeft теперь выглядит следующим образом:
public static Dictionary<K, V> MergeLeft<K, V>(this Dictionary<K, V> me, params IDictionary<K, V>[] others)
{
var newMap = new Dictionary<K, V>(me, me.Comparer);
foreach (IDictionary<K, V> src in
(new List<IDictionary<K, V>> { me }).Concat(others))
{
// ^-- echk. Not quite there type-system.
foreach (KeyValuePair<K, V> p in src)
{
newMap[p.Key] = p.Value;
}
}
return newMap;
}
Я бы сделал это так:
dictionaryFrom.ToList().ForEach(x => dictionaryTo.Add(x.Key, x.Value));
Просто и легко. Согласно этому сообщению в блоге это даже быстрее, чем большинство циклов, поскольку его базовая реализация обращается к элементам по индексу, а не по счетчику (см. Этот ответ) .
Конечно, при наличии дубликатов будет выдано исключение, поэтому вам придется проверить перед слиянием.
Как насчет того, чтобы добавить params
перегрузка?
кроме того, необходимо ввести их как IDictionary
для максимальной гибкости.
public static IDictionary<TKey, TValue> Merge<TKey, TValue>(IEnumerable<IDictionary<TKey, TValue>> dictionaries)
{
// ...
}
public static IDictionary<TKey, TValue> Merge<TKey, TValue>(params IDictionary<TKey, TValue>[] dictionaries)
{
return Merge((IEnumerable<TKey, TValue>) dictionaries);
}
Попробуйте следующий
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);
}
Тривиальное решение было бы:
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;
}
Обратите внимание, что, если Вы используете дополнительный метод под названием, 'Добавляют', Вы добираетесь для использования инициализаторов набора для объединения как много словарей по мере необходимости как это:
public static void Add<K, V>(this Dictionary<K, V> d, Dictionary<K, V> other) {
foreach (var kvp in other)
{
if (!d.ContainsKey(kvp.Key))
{
d.Add(kvp.Key, kvp.Value);
}
}
}
var s0 = new Dictionary<string, string> {
{ "A", "X"}
};
var s1 = new Dictionary<string, string> {
{ "A", "X" },
{ "B", "Y" }
};
// Combine as many dictionaries and key pairs as needed
var a = new Dictionary<string, string> {
s0, s1, s0, s1, s1, { "C", "Z" }
};
Упрощенный от использования по сравнению с моим более ранним ответом с bool значением по умолчанию неразрушающего слияния, если существующий или перезапись полностью, если верный вместо того, чтобы использовать перечисление. Это все еще удовлетворяет моим собственным потребностям без любого более необычного кода, когда-либо требуемого:
using System.Collections.Generic;
using System.Linq;
public static partial class Extensions
{
public static void Merge<K, V>(this IDictionary<K, V> target, IDictionary<K, V> source, bool overwrite = false)
{
source.ToList().ForEach(_ => {
if ((!target.ContainsKey(_.Key)) || overwrite)
target[_.Key] = _.Value;
});
}
}
Вот вспомогательная функция, которую я использую:
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);
}
}
}
Dictionary<String, String> allTables = new Dictionary<String, String>();
allTables = tables1.Union(tables2).ToDictionary(pair => pair.Key, pair => pair.Value);
Это не сработает, если есть несколько ключей («правые» клавиши заменяют «лефтерные»), может объединить несколько словарей (при желании) и сохранить тип (с ограничением, что для этого требуется значимая общедоступная версия по умолчанию. конструктор):
public static class DictionaryExtensions
{
// Works in C#3/VS2008:
// Returns a new dictionary of this ... others merged leftward.
// Keeps the type of 'this', which must be default-instantiable.
// Example:
// result = map.MergeLeft(other1, other2, ...)
public static T MergeLeft<T,K,V>(this T me, params IDictionary<K,V>[] others)
where T : IDictionary<K,V>, new()
{
T newMap = new T();
foreach (IDictionary<K,V> src in
(new List<IDictionary<K,V>> { me }).Concat(others)) {
// ^-- echk. Not quite there type-system.
foreach (KeyValuePair<K,V> p in src) {
newMap[p.Key] = p.Value;
}
}
return newMap;
}
}