Add items to a collection if the collection does NOT already contain it by comparing a property of the items?

michael picture michael · Jun 13, 2011 · Viewed 69k times · Source

Basically, how do I make it so I can do something similar to: CurrentCollection.Contains(...), except by comparing if the item's property is already in the collection?

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?

Answer

R. Martinho Fernandes picture R. Martinho Fernandes · Jun 13, 2011

You start by finding which elements are not already in the collection:

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

And then just add them:

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

Note that the first operation may have quadratic complexity if the size of DownloadedItems is close to the size of CurrentCollection. If that ends up causing problems (measure first!), you can use a HashSet to bring the complexity down to linear:

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