Tech
Forums
Jobs
Books
Events
Interviews
Live
More
Learn
Training
Career
Members
Videos
News
Blogs
Contribute
Article
Blog
Video
Ebook
Interview Question
Collapse
Feed
Dashboard
Wallet
Learn
Achievements
Network
Rewards
SharpGPT
Premium
Contribute
Article
Blog
Video
Ebook
Interview Question
Register
Login
A DistinctBy extension that takes a Lambda for Distinct
WhatsApp
Mike Gold
15y
30.9
k
0
1
25
Blog
Wouldn't it be nice to have an extension for Distinct that just takes a comparison function? That way you could just pass in the lambda comparison into your Distinct method. After searching on the web, I found a combination of solutions that works pretty well. This one by
Brendan Enrick
is perfect for what I need. I modified it a bit so it works for the Equals Operator. See below:
First we need to create an IEqualityComparer that takes a lambda expression. I used Brendan's, but modified GetHashCode so it is ignored and handled in the Equal operator as someone in his blog suggested.
using
System;
using
System.Collections.Generic;
using
System.Linq;
namespace
Ows.Composite.Core
{
public
class
LambdaComparer
<T> :
IEqualityComparer
<T>
{
private
readonly
Func
<T, T,
bool
> lambdaComparer;
private
readonly
Func
<T,
int
> lambdaHash;
public
LambdaComparer(
Func
<T, T,
bool
> lambdaComparer) :
this
(lambdaComparer, o => o.GetHashCode())
{
}
public
LambdaComparer(
Func
<T, T,
bool
> lambdaComparer,
Func
<T,
int
> lambdaHash)
{
if
(lambdaComparer ==
null
)
throw
new
ArgumentNullException
(
"lambdaComparer"
);
if
(lambdaHash ==
null
)
throw
new
ArgumentNullException
(
"lambdaHash"
);
this
.lambdaComparer = lambdaComparer;
this
.lambdaHash = lambdaHash;
}
public
bool
Equals(T x, T y)
{
return
lambdaComparer(x, y);
}
public
int
GetHashCode(T obj)
{
return
0;
}
}
public
static
class
Ext
{
public
static
IEnumerable
<TSource> Except<TSource>(
this
IEnumerable
<TSource> first,
IEnumerable
<TSource> second,
Func
<TSource, TSource,
bool
> comparer)
{
return
first.Except(second,
new
LambdaComparer
<TSource>(comparer));
}
}
}
Next, we can create an extension named
DistinctBy
that will simply call Distinct with an instance of this lambda comparer called DistinctBy. We'll write the extension so that we only need to pass in an anonymous delegate to determine equality of our list elements
public
static
IEnumerable
<TSource> DistinctBy<TSource>(
this
IEnumerable
<TSource> items,
Func
<TSource, TSource,
bool
> equalityComparer )
where
TSource:
class
{
return
items.Distinct(
new
LambdaComparer
<TSource>(equalityComparer));
}
That's it!
Here is an example of how to use our new DistinctBy extension to obtain a distinct list of people by name.
var distinctPeople = people.DistinctBy((x, y) => x.Name == y.Name)
Up Next
Working With Inner Join Using LINQ And Lambda
Ebook Download
View all
Printing in C# Made Easy
Read by 22.3k people
Download Now!
Learn
View all
Membership not found