How to get a distinct list from a List of objects?

109,751

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())
Share:
109,751
Willem
Author by

Willem

.net Fan Love wpf MVVM + M

Updated on October 15, 2020

Comments

  • Willem
    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 from List<MyClass> someList, but only comparing it to Prop2.

  • zerkms
    zerkms about 13 years
    @Jon, does it really worth to use MoreLINQ for such things instead of implementing IEqualityComparer for IEnumerable.Distinct?
  • Jon Skeet
    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
    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
    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
    Ilya Smagin about 13 years
    DistinctBy is nice, but what if i want to implement more complex logic, like 2 fields?
  • Jon Skeet
    Jon Skeet about 13 years
    @Ilya: That's easy: foo.DistinctBy(x => new { x.Prop1, x.Prop2 });
  • Jon Skeet
    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
    Willem about 13 years
    @Jon: Thanks, thats perfect. =)
  • Ilya Smagin
    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
    Iman Mahmoudinasab about 10 years
    What should be happened if we call p.Distinct(); without new Comparer() parameter? In general ListOfObjects.Distinct() how works?
  • Ilya Smagin
    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
    RJB almost 9 years
    Also works with multiple properties: someList.GroupBy(elem=> new { elem.Prop1, elem.Prop2, elem.Prop3 }).Select(group=>group.First());
  • Tejasvi Hegde
    Tejasvi Hegde about 7 years
    This should have been accepted answer. It does not depend on any external libraries and clean
  • Parsa
    Parsa about 7 years
    How can we use Distinict , without writing " new Comparer() " as @ImanMahmoudinasab said ?
  • Iman Mahmoudinasab
    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
    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 example pList contains a twice and using pList.Distinc() will give you just one a and one b. Notice that both a and b has equal name: Iman. So pList.Distinc().Count() is 2. but with a comparer pList.Distinc(new NameComparer()).Count() is 1.
  • MarceloBarbosa
    MarceloBarbosa about 7 years
    OMG, this is so... so... Satisfying. Thanks!
  • Jon Skeet
    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 read someList before it yields any elements. I would say the MoreLINQ approach is cleaner.
  • Tejasvi Hegde
    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
    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
    Tejasvi Hegde about 7 years
    @JonSkeet Sorry, I some how I couldn't look at edit option :)
  • Mubashar Shahzad
    Mubashar Shahzad over 5 years
    This really helped me a lot. we can also add .ToList() at the end. btw really helpful
  • Samy Sammour
    Samy Sammour about 5 years
    This is awesome! I love this solution
  • WtFudgE
    WtFudgE about 5 years
    epic, no need to actually use morelinq, just implement their distinctby