Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distinct() with lambda?

Right, so I have an enumerable and wish to get distinct values from it.

Using System.Linq, there's, of course, an extension method called Distinct. In the simple case, it can be used with no parameters, like:

var distinctValues = myStringList.Distinct(); 

Well and good, but if I have an enumerable of objects for which I need to specify equality, the only available overload is:

var distinctValues = myCustomerList.Distinct(someEqualityComparer); 

The equality comparer argument must be an instance of IEqualityComparer<T>. I can do this, of course, but it's somewhat verbose and, well, cludgy.

What I would have expected is an overload that would take a lambda, say a Func<T, T, bool>:

var distinctValues = myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId); 

Anyone know if some such extension exists, or some equivalent workaround? Or am I missing something?

Alternatively, is there a way of specifying an IEqualityComparer inline (embarrass me)?

Update

I found a reply by Anders Hejlsberg to a post in an MSDN forum on this subject. He says:

The problem you're going to run into is that when two objects compare equal they must have the same GetHashCode return value (or else the hash table used internally by Distinct will not function correctly). We use IEqualityComparer because it packages compatible implementations of Equals and GetHashCode into a single interface.

I suppose that makes sense.

like image 469
Tor Haugen Avatar asked Aug 19 '09 13:08

Tor Haugen


People also ask

What does distinct () do in C#?

C# Linq Distinct() method removes the duplicate elements from a sequence (list) and returns the distinct elements from a single data source. It comes under the Set operators' category in LINQ query operators, and the method works the same way as the DISTINCT directive in Structured Query Language (SQL).

How does Linq distinct work?

LINQ Distinct operator removes all the duplicate values from the collection and finally returns the dissimilar or unique values. The LINQ Distinct operator available in only Method Syntax and it not supports the Query Syntax. LINQ Distinct is an operator which comes under Set Operator.

What is distinct method?

The Distinct<TSource>(IEnumerable<TSource>) method returns an unordered sequence that contains no duplicate values. It uses the default equality comparer, Default, to compare values.


2 Answers

It looks to me like you want DistinctBy from MoreLINQ. You can then write:

var distinctValues = myCustomerList.DistinctBy(c => c.CustomerId); 

Here's a cut-down version of DistinctBy (no nullity checking and no option to specify your own key comparer):

public static IEnumerable<TSource> DistinctBy<TSource, TKey>      (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {     HashSet<TKey> knownKeys = new HashSet<TKey>();     foreach (TSource element in source)     {         if (knownKeys.Add(keySelector(element)))         {             yield return element;         }     } } 
like image 26
Jon Skeet Avatar answered Oct 12 '22 23:10

Jon Skeet


IEnumerable<Customer> filteredList = originalList   .GroupBy(customer => customer.CustomerId)   .Select(group => group.First()); 
like image 180
Carlo Bos Avatar answered Oct 13 '22 00:10

Carlo Bos