2016-01-27 135 views
1

我有一個dictionary<string, Foo>,其中X數量的元素。字典密鑰包含Foo.Id。我也有一個List<Foo> newFoos,在我的情況下,它包含的元素少於字典。所以我想要做的是有一個新的List<Foo>,所有元素都在newFoos,但不在我的字典中。獲取兩個大型列表之間的所有不匹配元素

我解決了這個利用:

var list = MyDict.Where(x => newFoos.All(y => y.Id != x.Key)).ToList(); 

但這樣做的問題是在我的情況下的性能,它必須是一些更容易和更快的方式?而請勿使用除/交叉,覆蓋equals

public class Program { 

    public static Dictionary<int, Foo> MyDict { get; set; } = new Dictionary<int, Foo>(); 
    private static void Main(string[] args) { 
     for (int i = 0; i < 2000; i++) { 
      MyDict.Add(i, new Foo() {Id = i}); 
     } 

     var newFoos = new List<Foo>(); 
     for (int i = 0; i < 1500; i++) { 
      newFoos.Add(new Foo() { Id = i }); 
     } 

     var list = MyDict.Where(x => newFoos.All(y => y.Id != x.Key)).ToList(); 
    } 
} 

public class Foo { 

    public int Id { get; set; } 

    //More properties 

} 

當使用我的testcode上面我覺得不慢,但原理是一樣的

+2

'MyDict'我討厭那個變量名。 – JonH

+1

提高工作的代碼是題外話和適合更好地http://codereview.stackexchange.com/ –

+0

@TimSchmelter - 真笑 – JonH

回答

3
var list = newFoos.Where(x => !MyDict.ContainsKey(x.Id)).ToList(); 

這應該是因爲檢查更有效如果一個關鍵字在字典中應該快於查找列表中的項目。

+0

這是明顯的改善,但目前還不清楚,如果OP是尋找這樣的答案,因爲他們已經辭退除的做法,本質上是一樣的了。 –

0

我認爲列表中的索引訪問比使用枚舉器稍快。如前所述,檢查重點所有腦幹也比訪問每個項目要快得多,這導致了對... ...的containsKey

 List<Foo> addedFoos = new List<Foo>(); 
     for (int i = 0; i < newFoos.Count; i++) 
     { 
      Foo current = newFoos[i]; 
      if (MyDict.ContainsKey(current.Id)) 
      { 
       addedFoos.Add(current); 
       //MyDict.Add(current.Id, current); /* see remark below */ 
      } 
     } 

     //addedFoos.ForEach(item => MyDict.Add(item.Id, item.Value)); /* see remark below */ 

如果您打算將它們添加到字典中,取決於量在找到它們而不是在循環中添加項目可能會更好,因爲否則,您將放大字典,同時使用永遠不會導致命中的項目進行搜索。

相關問題