LINQ to remove specific elements from IList <T> based on IList <int>
How to use LINQ to remove specific elements from an IList based on another IList. I need to remove entries from list1, where the ID is in list2. Below is a sample code,
class DTO { Prop int ID, Prop string Name } IList<DTO> list1; IList<int> list2; foreach(var i in list2) { var matchingRecord = list1.Where(x.ID == i).First(); list1.Remove(matchingRecord); } Here is how I do it, is there a better way to do the same.
I would use this approach:
var itemsToRemove = list1.Where(x => list2.Contains(x.ID)).ToList(); foreach(var itemToRemove in itemsToRemove) list1.Remove(itemToRemove); This approach removes elements in place. It is best used when there are many elements in list1 and several in list2 .
If the number of items in list1 and list2 similar, the approach from Cuong Le is a good alternative.
You can write the extension method "RemoveAll ()" for IList<T> , which works just like List.RemoveAll() . (This is usually useful for storage in a shared class library.)
For example (error checking removed for clarity, you need to check that the parameters are not equal to zero):
public static class IListExt { public static int RemoveAll<T>(this IList<T> list, Predicate<T> match) { int count = 0; for (int i = list.Count - 1; i >= 0; i--) { if (match(list[i])) { ++count; list.RemoveAt(i); } } return count; } Then, to remove items from list1, as required, it will really become as simple as:
list1.RemoveAll(item => list2.Contains(item.ID)); You can use Where to simplify:
list1 = list1.Where(x => !list2.Contains(x.ID)) .ToList(); But you really need to remove in place, prefer @DanielHilgarth to reply