How do I use a custom comparer with the Linq Distinct method?

15,101

You're implementing your comparer as an IComparer<T>, the LINQ method overload requires an implementation of IEqualityComparer:

private class GribulatorComparer : IEqualityComparer<Gribulator> {
  public bool Equals(Gribulator g1, Gribulator g2) {
    return g1.ID == g2.ID;
  }
}

edit:

For clarification, the IComparer interface can be used for sorting, as that's basically what the Compare() method does.

Like this:

items.OrderBy(x => new ItemComparer());

private class ItemComparer : IComparer<Item>
{
    public int Compare(Item x, Item y)
    {
        return x.Id.CompareTo(y.Id)
    }
}

Which will sort your collection using that comparer, however LINQ provides a way to do that for simple fields (like an int Id).

items.OrderBy(x => x.Id);
Share:
15,101

Related videos on Youtube

Avrohom Yisroel
Author by

Avrohom Yisroel

I'm a self-employed programmer with far too much interest in learning new things that I'll probably never have chance to use in real life. My day job consists of pulling data from a database, displaying it on a window, waiting for the user to make some edits and then saving the data back into the database. Sound familiar? If I'm lucky, I get to generate a report or send an email along the way. Pardon me while I yawn. My out-of-work activities involve trying to get my head around the sort of stuff I'd really like to do for a job, like machine learning, natural algorithms and so on. I dabble in these, occasionally post some ramblings on my blog (that no-one reads, so I can post what I like). I'm a huge fan of Linq, and have been trying to expand my horizons by learning some less C-like languages, such as Racket (LISP) and F#. Out of work hours, I like tickling my children (I have lots to tickle!), growing carnivorous plants and studying ancient legal texts.

Updated on September 15, 2022

Comments

  • Avrohom Yisroel
    Avrohom Yisroel over 1 year

    I was reading a book about Linq, and saw that the Distinct method has an overload that takes a comparer. This would be a good solution to a problem I have where I want to get the distinct entities from a collection, but want the comparison to be on the entity ID, even if the other properties are different.

    According to the book, if I have a Gribulator entity, I should be able to create a comparer like this...

    private class GribulatorComparer : IComparer<Gribulator> {
      public int Compare(Gribulator g1, Gribulator g2) {
        return g1.ID.CompareTo(g2.ID);
      }
    }
    

    ...and then use it like this...

    List<Gribulator> distinctGribulators
      = myGribulators.Distinct(new GribulatorComparer()).ToList();
    

    However, this gives the following compiler errors...

    'System.Collections.Generic.List' does not contain a definition for 'Distinct' and the best extension method overload 'System.Linq.Enumerable.Distinct(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEqualityComparer)' has some invalid arguments

    Argument 2: cannot convert from 'LinqPlayground.Program.GribulatorComparer' to 'System.Collections.Generic.IEqualityComparer'

    I've searched around a bit, and have seen plenty of examples that use code like this, but no complaints about compiler errors.

    What am I doing wrong? Also, is this the best way of doing this? I want a one-off solution here, so don't want to start changing the code for the entity itself. I want the entity to remain as normal, but just in this one place, compare by ID only.

    Thanks for any help.

  • Avrohom Yisroel
    Avrohom Yisroel over 11 years
    Thanks Peter, that explains it! The example I was using in the book was for OrderBy, but he had referred to it from where he discussed Distinct, and I hadn't picked up on the fact that I needed a different interface. Wasn't very clear in the book actually :(
  • Avrohom Yisroel
    Avrohom Yisroel over 11 years
    By the way, do you know if there is a way to do this with an anonymous function, instead of having to create a separate class for the comparer? Seems like overkill
  • Peter Davidsen
    Peter Davidsen over 11 years
    As far as I know, there isn't. I've actually been thinking about overloading linq operators with stuff like that.
  • Avrohom Yisroel
    Avrohom Yisroel over 11 years
    Shame, because for a one-off like my situation, it's overkill to create a whole new class. I've got used to throwing anonymous functions around! Thanks again.
  • Elliot Starks
    Elliot Starks almost 7 years
    I think it's worth mentioning that writing a custom IEqualityComparer also requires an implementation of GetHashCode()