So we'll start out with just a simple SetEquals
, and go from there. HashSet
already has an implementation of such a method that can compare two sets for equality, so we can just create a wrapper around that so that we can use it with any type of sequence:
public static bool SetEquals<T>(this IEnumerable<T> first, IEnumerable<T> second,
IEqualityComparer<T> comparer = null)
{
return new HashSet<T>(second, comparer ?? EqualityComparer<T>.Default)
.SetEquals(first);
}
Next, to account for the fact that you have a bag, not a set, we can just take the two sequences that you have, group them, and project that out into a pair that has the item along with the count of matching items. If we do that for both sets then we can compare these sequences of objects as sets, and see if they're set equal. If the key-count pair sequences are both set-equal, then the original sequences are bag-equal:
public static bool BagEquals<T>(
this IEnumerable<T> first,
IEnumerable<T> second)
{
Func<IEnumerable<T>, IEnumerable<KeyValuePair<T, int>>> groupItems =
sequence => sequence.GroupBy(item => item,
(key, items) => new KeyValuePair<T, int>(key, items.Count()));
return groupItems(first)
.SetEquals(groupItems(second));
}