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?
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();
}
}
If you override Equals for your customer object, then just use
A.Except(B);
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With