How to get a distinct list from a List of objects?
Solution 1
Unfortunately there's no really easy built-in support for this in the framework - but you can use the DistinctBy
implementation I have in MoreLINQ.
You'd use:
var distinctList = someList.DistinctBy(x => x.Prop2).ToList();
(You can take just the DistinctBy
implementation. If you'd rather use a Microsoft implementation, I believe there's something similar in the System.Interactive assembly of Reactive Extensions.)
Solution 2
You can emulate the effect of DistinctBy
using GroupBy
and then just using the first entry in each group. Might be a bit slower that the other implementations though.
someList.GroupBy(elem=>elem.Prop2).Select(group=>group.First());
Solution 3
you need to use .Distinct(..);
extension method.
Here's a quick sample:
public class Comparer : IEqualityComparer<Point>
{
public bool Equals(Point x, Point y)
{
return x.X == y.X;
}
public int GetHashCode(Point obj)
{
return (int)obj.X;
}
}
Do not forget about GetHashCode
.
Usage:
List<Point> p = new List<Point>();
// add items
p.Distinct(new Comparer());
Solution 4
Override Equals(object obj) and GetHashCode() methods:
class MyClass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
public int Prop3 { get; set; }
public override bool Equals(object obj)
{
return ((MyClass)obj).Prop2 == Prop2;
}
public override int GetHashCode()
{
return Prop2.GetHashCode();
}
}
and then just call:
List<MyClass> distinctList = someList.Distinct().ToList();
Solution 5
Since the introduction of value tuples, if you want a LINQ equivalent to SQL's DISTINCT
items.GroupBy(item => (item.prop1, item.prop2, ...)).Select(group => group.First())
Comments
-
Willem over 3 years
I have a
List<MyClass> someList
.class MyClass { public int Prop1... public int Prop2... public int Prop3... }
I would like to know how to get a new distinct
List<MyClass> distinctList
fromList<MyClass> someList
, but only comparing it toProp2
. -
zerkms about 13 years@Jon, does it really worth to use MoreLINQ for such things instead of implementing
IEqualityComparer
forIEnumerable.Distinct
? -
Jon Skeet about 13 years@zerkms: Personally I would use MoreLINQ or Reactive Extensions, yes... it really doesn't take much effort to include it, and the calling code ends up being more readable IMO.
-
zerkms about 13 years@Jon, I just worry about adding dependencies on 3rd party code. In other hand - built in solution obliges us to write bloated code... :-S
-
Stilgar about 13 years@Jon do you happen to know why they didn't add an overload to Distinct that takes a lambda? Same question for the overload of Contains.
-
Ilya Smagin about 13 yearsDistinctBy is nice, but what if i want to implement more complex logic, like 2 fields?
-
Jon Skeet about 13 years@Ilya: That's easy:
foo.DistinctBy(x => new { x.Prop1, x.Prop2 });
-
Jon Skeet about 13 years@Stilgar: I don't know... there are various additional features which would be nice to have in LINQ. Of course they'd then have to be implemented in LINQ to SQL etc as well...
-
Willem about 13 years@Jon: Thanks, thats perfect. =)
-
Ilya Smagin about 13 years@Jon, thanks. @zerkms: if you do not want to reference 3rd party code, write it yourself. it's pretty much easy to do.
-
Iman Mahmoudinasab about 10 yearsWhat should be happened if we call
p.Distinct();
withoutnew Comparer()
parameter? In generalListOfObjects.Distinct()
how works? -
Ilya Smagin almost 9 years@ImanMahmoudinasab, in general, .NET will use equality methods(Equals and GetHashCode) from the object. If they are not defined, they would be compared by reference, therefore, an object would be equal to itself only.
-
RJB almost 9 yearsAlso works with multiple properties:
someList.GroupBy(elem=> new { elem.Prop1, elem.Prop2, elem.Prop3 }).Select(group=>group.First());
-
Tejasvi Hegde about 7 yearsThis should have been accepted answer. It does not depend on any external libraries and clean
-
Parsa about 7 yearsHow can we use Distinict , without writing " new Comparer() " as @ImanMahmoudinasab said ?
-
Iman Mahmoudinasab about 7 years@Parsa writing distinct without comparer is easy
p.Distinct();
. Distinct without comparer is usefull only when you want to check two instance is same referane (same memory) not equal (diferent memory but equal property value). -
Iman Mahmoudinasab about 7 years@Parsa Example:
var a=new Person("Iman"); var b=new Person("Iman"); var pList=new List<Person>(); pList.Add(a); pList.Add(b); pList.Add(a);
in this examplepList
containsa
twice and usingpList.Distinc()
will give you just onea
and oneb
. Notice that botha
andb
has equal name:Iman
. SopList.Distinc().Count()
is 2. but with a comparerpList.Distinc(new NameComparer()).Count()
is 1. -
MarceloBarbosa about 7 yearsOMG, this is so... so... Satisfying. Thanks!
-
Jon Skeet about 7 years@TejasviHegde: Well, it has downsides compared with using
DistinctBy
as well: 1) it takes more memory, as it builds a group for every element; 2) it can't stream the results - it has to completely readsomeList
before it yields any elements. I would say the MoreLINQ approach is cleaner. -
Tejasvi Hegde about 7 years@JonSkeet Thanks! I didn't think from this angle :) Btw. I just went through the code of your library, I loved the coding style and neat implementation!
-
Jon Skeet about 7 years@TejasviHegde: It would be helpful if in future you could just suggest the relevant edit to be approved...
-
Tejasvi Hegde about 7 years@JonSkeet Sorry, I some how I couldn't look at edit option :)
-
Mubashar Shahzad over 5 yearsThis really helped me a lot. we can also add .ToList() at the end. btw really helpful
-
Samy Sammour about 5 yearsThis is awesome! I love this solution
-
WtFudgE about 5 yearsepic, no need to actually use morelinq, just implement their distinctby