2017-10-12 113 views
0

我有五个字典的类型Dictionary<ThingId, Thing>Dictionary<ThingId, List<Thing>>。我想对所有的人都遍历的规则如下:迭代几个字典的联合

  1. 迭代上的所有ThingId不重复
  2. 对于每个键(又名每个ID),得到的东西从所有词典列表而不将它们混合(它们不具有相同的功能含义)。

现在,我这样做:

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); 
    } 
} 

是否有可能与Linq做到这一点?例如,做一个字典键的联合,并从值中创建匿名类(需要时使用“默认”值)?

我看着Union方法,但它不是我想要的。

+0

我不太了解linq union,但也许你可以使用AsParalell()来改善itteration performan CE? – thanatorr

回答

1

这个人是非常低效的性能,明智的,但使用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>()) 
     ); 
    } 

另一种方法是延长您的字典,然后使用该扩展名:

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; 
     } 
    } 

,那么你可以使用

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>()) 
     ); 
+0

这与Linq算法基本相同,不是吗? – Boiethios

+0

一种。我认为它更糟糕,因为它不使用索引器访问字典值,而是使用FirstOrDefault。我没有真正测试过它,但是我怀疑Linq可以正确地优化它,所以我们不用一个快速的索引器访问,而是逐个逐字地遍历字典匹配键。但是,是的,它与Linq :) – rs232

+0

至少,它更具可读性。我做了一个研究,也可以从'IEnumerable'创建'HashSet':https://stackoverflow.com/questions/3471899/how-to-convert-linq-results-to-hashset-or-hashedset – Boiethios