Ваша проблема, похоже, связана с интерфейсом IDictionary‹>. Предполагается, что для каждого ключа существует только одно значение. Я полагаю, что вы скорее хотите перейти к LINQ-ish IEnumerable<IGrouping<TKey,TValue>>
, который представляет собой список коллекций значений с ключами.
LINQ создает такие объекты, когда вы выполняете вызовы .GroupBy или .ToLookup.
Тогда давайте поиграем:
using System.Linq;
Dictionary<string, dynamic> A = ...;
Dictionary<string, dynamic> B = ...;
// naiive atempt:
var lookup =
A.Keys.Concat(B.Keys)
.ToDictionary(key => key, key => new dynamic[]{ A[key], B[key] } ));
Конечно, это не сработает, но я написал его, чтобы посмотреть, какие проблемы он выявит. Во-первых, вы, вероятно, получите дубликаты ключей при объединении. Тогда не все ключи находятся в A и B, поэтому индексаторы будут выбрасывать. Затем я случайно предположил, что исходные объекты были строкой-к-одному значению, и вы, вероятно, будете работать с уже столкнувшимися объектами. Затем используются только 2 объекта A/B, в то время как вы можете работать с несколькими.
IEnumerable<Dictionary<string, dynamic>> inputs = ....;
// btw. GropuBy returns a lookup, too :) a key -> all matches
var matched_by_keys = inputs.GroupBy(pair => pair.Key);
var final = matched_by_keys.ToDictionary(group => group.Key, group => group);
Посмотреть там. Я взял все словари и «просто соединил их в пары» в соответствии с их ключами. В результате у меня есть поиск, который связывает каждый существующий ключ с серией значений, которые ранее были назначены этому ключу. Полученный matched_by_keys
является Enumerable, а не словарем, поэтому позже он был переведен в него. Посмотрите на параметры ToDictionary: сама группа является IEnumerable, просто нужно было указать ключ, и группа не изменилась.
Тем не менее, ввод работает только с однозначным IDictionary. Если вам нужно делать такие вещи и с многозначными входными данными, вы можете легко преобразовать IDictionaries в поиск и выполнять над ними операции:
IEnumerable<Dictionary<string, dynamic>> inputs1 = ....; // normal items
IEnumerable<ILookup<string, dynamic>> inputs2 = ....; // items that previously already collided
var allAsLookups =
inputs1.ToLookup(pair => pair.Key, pair => pair.Value)
.Concat( inputs2 );
// btw. GropuBy returns a lookup, too :) a key -> all matches
var matched_by_keys = lookups.GroupBy(lk => lk.Key);
var final1 = matched_by_keys.ToDictionary(group => group.Key, group => group.SelectMany(s=>s));
Обратите внимание, как должны были быть переведены последние группы. В этом примере group имеет значение не IEnumerable<Value>
, а IEnumerable<IEnumerable<Value>>
, потому что входным данным разрешено быть многозначным, даже если они имеют только одно значение. Итак, его нужно было сгладить, и это сделал SelectMany. Это, в свою очередь, не нужно было ничего проецировать, так как элемент уже был IEnumerable, поэтому s=>s было достаточно.
Используя различные перегрузки GroupBy, ToLookup и ToDictionary, вы можете добиться множества полезных эффектов. Играйте с перегрузками!
person
quetzalcoatl
schedule
15.08.2012