I know how it's possible to use anonymous types to group by a fixed list of values. What I want to do is group by an actual set of values.
For example, the result of this expression is 2.
new List<HashSet<int>> {
new HashSet<int> { 4 },
new HashSet<int> { 4 }
}.GroupBy (x => x).Count()
I'm looking for a way to put those sets in the same group so that the result would be 1. In python, this would be accomplished using frozenset
.
What's the cleanest way of doing this?
You can use the static HashSet<T>.CreateSetComparer
method for this purpose.
Return Value
Type: System.Collections.Generic.IEqualityComparer> An IEqualityComparer object that can be used for deep equality testing of the HashSet object.
new List<HashSet<int>> {
new HashSet<int> { 4 },
new HashSet<int> { 4 }
}.GroupBy (x => x, HashSet<int>.CreateSetComparer())
(I am assuming that you want to group both sets as "equal" -- the question is not terribly clear)
As is often the case with LINQ, the scaffolding to achieve this already exists and what needs to be done is to supply a custom IEqualityComparer<T>
to the appropriate method. In this instance this means using this overload.
Here's a generic IEqualityComparer<ISet<T>>
that declares two sets equal if their intersection is the same set as both of them:
class SetComparer<T> : IEqualityComparer<ISet<T>> {
public bool Equals(ISet<T> lhs, ISet<T> rhs) {
// null checks omitted
return lhs.SetEquals(rhs);
}
public int GetHashCode(ISet<T> set) {
// Not the best choice for a hash function in general,
// but in this case it's just fine.
return set.Count;
}
}
And here's how you would group both sets under the same umbrella:
new List<HashSet<int>> {
new HashSet<int> { 4 },
new HashSet<int> { 4 }
}.GroupBy (x => x, new SetComparer<int>()).Count();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With