Jimmy
Jimmy

Reputation: 2106

Using Linq not equals

I've 2 list collections in my C# app..A and B.

Both the collections have customer object which has Id and Name attributes.Typically, A has more items than B.

Using Linq,I want to return only those customers whose Id is in A but not in B.

How do I do this?

Upvotes: 8

Views: 27309

Answers (3)

Anthony Pegram
Anthony Pegram

Reputation: 126794

There are multiple approaches to take. The cleanest approach is to use the Except extension method if you have overriden Equals and GetHashCode. If you have not, there are other options.

// have you overriden Equals/GetHashCode?
IEnumerable<Customer> resultsA = listA.Except(listB);

// no override of Equals/GetHashCode? Can you provide an IEqualityComparer<Customer>?
IEnumerable<Customer> resultsB = listA.Except(listB, new CustomerComparer()); // Comparer shown below

// no override of Equals/GetHashCode + no IEqualityComparer<Customer> implementation?
IEnumerable<Customer> resultsC = listA.Where(a => !listB.Any(b => b.Id == a.Id));

// are the lists particularly large? perhaps try a hashset approach 
HashSet<int> customerIds = new HashSet<int>(listB.Select(b => b.Id).Distinct());
IEnumerable<Customer> resultsD = listA.Where(a => !customerIds.Contains(a.Id));

...

class CustomerComparer : IEqualityComparer<Customer>
{
    public bool Equals(Customer x, Customer y)
    {
        return x.Id.Equals(y.Id);
    }

    public int GetHashCode(Customer obj)
    {
        return obj.Id.GetHashCode();
    }
}

Upvotes: 21

Jim L
Jim L

Reputation: 2327

Expanding on Except, providing your own equality so you don't need to change your Equals behavior. I got this from here:

http://www.codeproject.com/KB/dotnet/LINQ.aspx#distinct

List<Customer> customersA = new List<Customer> { new Customer { Id = 1, Name = "A" }, new Customer { Id = 2, Name = "B" } };
List<Customer> customersB = new List<Customer> { new Customer { Id = 1, Name = "A" }, new Customer { Id = 3, Name = "C" } };

var c = (from custA in customersA
        select custA.Id).Distinct()
             .Except((from custB in customersB
            select custB.Id).Distinct());

Upvotes: 4

Larsenal
Larsenal

Reputation: 51146

If you override Equals for your customer object, then just use

A.Except(B);

Upvotes: 5

Related Questions