RikWare
...

LINQ Distinct without IEqualityComparer

Monday, 17 August 2009 22:11 by Richard Mason

One annoying issue with the LINQ Distinct function is that it requires an IEqualityComparer. Often I'd (and many others based on the info out there) would prefer to just provide a lamdba indicating which field to compare on, or simply a predicate for doing the compare.

There's at least one solution out there which uses a generic implementation of IEqualityComparer which works fine and another which simply implements the Distinct iteratively. Instead I figured you could instead build it up using Reduce... woops I mean Aggregate.

static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, T, bool> comparer)
{
  return list.Aggregate((IEnumerable<T>)new T[0],
    (a, b) => a.Any(c => comparer(c, b)) ? a : a.Concat(new[] {b}),
    a => a);
}
 
static IEnumerable<T> Distinct<T>(IEnumerable<T> list, Func<T, object> selector)
{
	return Distinct(list, (a, b) => selector(a).Equals(selector(b)));

 

Two versions, one for just specifying that the compare should happen on some calculated value and another for providing a custom compare function. 

Now this might not be the most efficient method of implementing this, but it's kind of nice, but I'm a bit unhappy with the fact that this is no longer a lazy list. I have a solution for that as well, but it's nowhere near as clean as this :(