您的问题似乎基于 IDictionary<> 接口。它假设每个键只有一个值。我相信您更愿意转向IEnumerable<IGrouping<TKey,TValue>>
表示键值集合列表的 LINQ-ish。
当您执行 .GroupBy 或 .ToLookup 调用时,LINQ 会发出此类对象。
那就玩吧:
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 的参数:Group 本身就是一个 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));
请注意现在必须翻译最后的组。在此示例中, groupis 不是IEnumerable<Value>
,而是因为允许IEnumerable<IEnumerable<Value>>
输入是多值的,即使它们只有 1 个值。所以,它必须被展平,这是由 SelectMany 完成的。这反过来不需要投影任何东西,因为该项目已经是 IEnumerable,所以 =>s 就足够了。
使用 GroupBy、ToLookup 和 ToDictionary 的不同重载,您可以实现许多有用的效果。玩超载!