Add IEnumerable & lt; Type & gt; To IList & lt; Type & gt; Where IList does not contain a primary key - LAMBDA

advertisements

I have an IList<Price> SelectedPrices. I also have an IEnumerable<Price> that gets retrieved at a later date. I would like to add everything from the latter to the former where the former does NOT contain the primary key defined in the latter. So for instance:

IList<Price> contains Price.ID = 1, Price.ID = 2, and IEnumerable<Price> contains Price.ID = 2, Price.ID = 3, and Price.ID = 4. What's the easiest way to use a lambda to add those items so that I end up with the IList containing 4 unique Prices? I know I have to call ToList() on the IList to get access to the AddRange() method so that I can add multiple items at once, but how do I select only the items that DON'T exist in that list from the enumerable?


I know I have to call ToList() on the IList to get access to the AddRange() method

This is actually not safe. This will create a new List<T>, so you won't add the items to your original IList<T>. You'll need to add them one at a time.

The simplest option is just to loop and use a contains:

var itemsToAdd = enumerablePrices.Where(p => !SelectedPrices.Any(sel => sel.ID == p.ID));
foreach(var item in itemsToAdd)
{
    SelectedPrices.Add(item);
}

However, this is going to be quadratic in nature, so if the collections are very large, it may be slow. Depending on how large the collections are, it might actually be better to build a set of the IDs in advance:

var existing = new HashSet<int>(SelectedPrices.Select(p => p.ID));
var itemsToAdd = enumerablePrices.Where(p => !existing.Contains(p.ID));
foreach(var item in itemsToAdd)
{
    SelectedPrices.Add(item);
}

This will prevent the routine from going quadratic if your collection (SelectedPrices) is large.