2011-06-13 79 views
25

基本上,我該如何做到這一點,所以我可以做類似於:CurrentCollection.Contains(...)的東西,除非比較該物品的屬性是否已經在集合中?如果集合尚未包含項目的屬性,則將項目添加到集合中?

public class Foo 
{ 
    public Int32 bar; 
} 


ICollection<Foo> CurrentCollection; 
ICollection<Foo> DownloadedItems; 

//LINQ: Add any downloaded items where the bar Foo.bar is not already in the collection? 

回答

34

你開始通過尋找哪些元素是不是已經在收集:

var newItems = DownloadedItems.Where(x => !CurrentCollection.Any(y => x.bar == y.bar)); 

然後只需添加他們:

foreach(var item in newItems) 
{ 
    CurrentCollection.Add(item); 
} 

注意,第一操作可能有二次的複雜性,如果大小的DownloadedItems接近大小CurrentCollection。如果這最終導致問題的(測量第一!),你可以使用一個HashSet帶來的複雜性降到線性:

// collect all existing values of the property bar 
var existingValues = new HashSet<Foo>(from x in CurrentCollection select x.bar); 
// pick items that have a property bar that doesn't exist yet 
var newItems = DownloadedItems.Where(x => !existingValues.Contains(x.bar)); 
// Add them 
foreach(var item in newItems) 
{ 
    CurrentCollection.Add(item); 
} 
3

可以調用Any方法,並傳遞一個值來比較對象的類型的任何財產集合中

if (!CurrentCollection.Any(f => f.bar == someValue)) 
{ 
    // add item 
} 

一個更完整的解決方案是:

DownloadedItems.Where(d => !CurrentCollection.Any(c => c.bar == d.bar)).ToList() 
    .ForEach(f => CurrentCollection.Add(f)); 
0
var newItems = DownloadedItems.Where(i => !CurrentCollection.Any(c => c.Attr == i.Attr)); 
0

你可以這樣做:

CurrentCollection.Any(x => x.bar == yourGivenValue) 
8

使用R.Martinho費爾南德斯方法,並轉換到1線:

CurrentCollection.AddRange(DownloadedItems.Where(x => !CurrentCollection.Any(y => y.bar== x.bar))); 
1

或者用All

CurrentCollection 
    .AddRange(DownloadedItems.Where(x => CurrentCollection.All(y => y.bar != x.bar))); 
1

您可以使用Enumerable.Except

它將比較僅顯示在第一個列表中的兩個列表並返回元素。

CurrentCollection.AddRange(DownloadedItems.Except(CurrentCollection));