4

At the end of my current LINQ query, I have data which is in the form of an IEnumerable<IEnumerable<int>>, with several duplicate combinations.

For example:

{
  {5, 20}
  {5, 20}
  {10, 15}
}

What's the best way to filter these so that each set is only represented once? A LINQ answer would be ideal so I can chain it further.

Bobson
  • 13,498
  • 5
  • 55
  • 80
  • 4
    You need an `IEqualityComparer>`. – SLaks May 14 '13 at 18:01
  • 2
    How do you define "equal"? Does order matter? – D Stanley May 14 '13 at 18:01
  • @DStanley - It doesn't - I'm currently ordering the data before it gets to this step, but if the equality test can handle it in an unordered manner, I can take that bit out. – Bobson May 14 '13 at 18:03
  • 1
    @SLaks - As in [this answer](http://stackoverflow.com/a/14675741/298754)? (Now that I know what to search for, it's easy to find.) **Edit:** Or as in recursive's below, of course. – Bobson May 14 '13 at 18:07
  • Yes; exactly. Ideally, the hashcode should be order sensitive (i.e., the lambda shouldn't be commutatibe) – SLaks May 14 '13 at 18:11
  • 2
    If order does not matter, none of those will work, because `SequenceEqual()` is order-sensitive. – SLaks May 14 '13 at 18:11

1 Answers1

7

If you create a sequence equality comparer like this:

class SequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>> {
    public bool Equals(IEnumerable<T> a, IEnumerable<T> b) {
        if (a == null) return b == null;
        if (b == null) return false;
        return a.SequenceEqual(b);
    }

    public int GetHashCode(IEnumerable<T> val) {
        return val.Where(v => v != null)
                .Aggregate(0, (h, v) => h ^ v.GetHashCode());
    }
}

Then, you can call .Distinct(new SequenceEqualityComparer<int>()).

recursive
  • 83,943
  • 34
  • 151
  • 241