2016-01-27 90 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 */ 

如果您打算将它们添加到字典中,取决于量在找到它们而不是在循环中添加项目可能会更好,因为否则,您将放大字典,同时使用永远不会导致命中的项目进行搜索。

相关问题