I have five dictionaries of type Dictionary<ThingId, Thing>
and Dictionary<ThingId, List<Thing>>
. I want to iterate on all of them with the following rules:
For now, I do this:
void DoSomething(Dictionary<ThingId, Thing> dic1, Dictionary<ThingId, List<Thing>> dic2, Dictionary<ThingId, List<Thing>> dic3) // only 3 to not clutter the code
{
var ids = new HashSet<ThingId>(dic1.Keys).AddRange(dic2.Keys).AddRange(dic3.Keys);
foreach (var id in ids)
{
Thing thing1;
List<Thing> things2;
List<Thing> things3;
if (!dic1.TryGetValue(id, out thing1)
{
//default
thing1 = new Thing(id);
}
if (!dic2.TryGetValue(id, out things2)
{
//default
things2 = new List<Thing>();
}
if (!dic3.TryGetValue(id, out things3)
{
//default
things3 = new List<Thing>();
}
DoSomethingElse(thing1, things2, things3);
}
}
Is it possible to do this with Linq
? For example do an union of the keys of the dictionaries and build anonymous class from the values (with the "default" values when needed)?
I looked at the Union
method, but it does not what I want.
答案 0 :(得分:1)
This one is pretty inefficient performance-wise, but with Linq:
void DoSomething(Dictionary<ThingId, Thing> dic1, Dictionary<ThingId, List<Thing>> dic2, Dictionary<ThingId, List<Thing>> dic3) // only 3 to not clutter the code
{
dic1.Keys.Union(dic2.Keys).Union(dic3.Keys).Distinct().ToList().ForEach(id =>
DoSomethingElse(
dic1.FirstOrDefault(d => d.Key == id).Value ?? new Thing(id),
dic2.FirstOrDefault(d => d.Key == id).Value ?? new List<Thing>(),
dic3.FirstOrDefault(d => d.Key == id).Value ?? new List<Thing>())
);
}
Another way would be to extend your Dictionary and then use that extension:
public static class DictionaryExtension
{
public static VType GetSafeValue<KType, VType>(this Dictionary<KType, VType> dic, KType key) where VType : class
{
VType v;
if (!dic.TryGetValue(key, out v))
{
return null;
}
return v;
}
}
then you may use
dic1.Keys.Union(dic2.Keys).Union(dic3.Keys).Distinct().ToList().ForEach(id =>
DoSomethingElse(
dic1.GetSafeValue(id) ?? new Thing(id),
dic2.GetSafeValue(id) ?? new List<Thing>(),
dic3.GetSafeValue(id) ?? new List<Thing>())
);