2017-10-12 59 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