64

I'm stuck with a LINQ query (or any other efficient means of accomplishing the same thing). Can someone show me how I can select all the items in one list that are not present in another list?

Basically, I have a list I formed by matching items between two other lists. I need to find all the items in the first list that matches weren't found for. Can someone fill in the stars in the second LINQ query below with the query that would achieve this goal? If I were using TSQL, I would do SELECT * NOT IN (), but I don't think LINQ allows that.

//Create some sample lists.
List<IdentifierLookupData> list1 = new List<IdentifierLookupData> { /*Init */ };
List<IdentifierLookupData> list2 = new List<IdentifierLookupData> { /*Init */ };

//Find all items in list1 and list2 that match and store them in joinItems.
var joinItems = (from d1 in list1
    join d2 in list2 on d1 equals d2
    select d1).ToList<IdentiferLookupData>();

//Find all items in list1 not in joinItems.
var deletedItems = (from d1 in list1
     ***select all items not found in joinItems list.***
Jacob
  • 77,566
  • 24
  • 149
  • 228
John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • 3
    Your exact title searched in google: http://www.google.com/search?sugexp=chrome,mod=4&sourceid=chrome&ie=UTF-8&q=LINQ+-+Find+all+items+in+one+list+that+aren't+in+another+list – Joe Jul 10 '12 at 17:49
  • 1
    @JoeTuskan And yet the question received up votes! – dlev Jul 10 '12 at 17:52
  • 1
    I can find anything on google, SO is a good site because I can type a question in 30 seconds, work on something else, and get the perfect expert-argued answer later without wasting any time or using the possibly inefficient first google answer and wasting time finding that out myself while I'm getting paid to get things done :p – John Humphreys Jul 10 '12 at 18:54
  • 2
    possible duplicate of [Use LINQ to get items in one List<>, that are not in another List<>](http://stackoverflow.com/questions/3944803/use-linq-to-get-items-in-one-list-that-are-not-in-another-list) – Jim G. Feb 26 '14 at 02:35

3 Answers3

131

Try using .Except extension method (docs):

var result = list1.Except(list2);

will give you all items in list1 that are not in list2.

IMPORTANT: Even though there's a link provided to MSDN docs for the method, I'll point this out here: Except only works out of the box for collections of primitive types, for POCOs/objects you need to implement IEquatable on that object.

Dimitri
  • 6,923
  • 4
  • 35
  • 49
  • 7
    But only if `IdentifierLookupData` implements `IEquatable` – Tim Schmelter Jul 10 '12 at 17:50
  • This answer really ought to be edited to say *Except only works out of the box for primitive lists, for POCOs/objects you need to implement IEquatable on that object. – jspinella Sep 29 '20 at 18:37
38

Try this:

var List2 = OriginalList.Where(item => !List1.Any(item2 => item2.ID == item.ID));
Nalan Madheswaran
  • 10,136
  • 1
  • 57
  • 42
  • 2
    I like this one because I can use it for two different types of lists, like with Dates. where I need to filter out the original list based on another list. +1 – Piotr Kula Oct 06 '17 at 09:19
  • I like this one too, because of the possibility to compare different types of lists. Great! – Molasar Feb 20 '19 at 23:50
11

The easiest way is to use the Except method.

var deletedItems = list1.Except(joinItems);

This will return the set of items in list1 that's not contained in joinItems

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454