If you don't care about duplicates (i.e. you'd consider {1, 2, 3}
to be equal to {1, 2, 3, 2}
) then:
new HashSet<int>(A).SetEquals(B)
(Or whatever type is the element type instead of int
).
Otherwise:
public static bool SequenceEqualUnordered<T>(IEnumerable<T> first, IEnumerable<T> second)
{
if (first == null)
return second == null; // or throw if that's more appropriate to your use.
if (second == null)
return false; // likewise.
var dict = new Dictionary<T, int>(); // You could provide a IEqualityComparer<T> here if desired.
foreach(T element in first)
{
int count;
dict.TryGetValue(element, out count);
dict[element] = count + 1;
}
foreach(T element in second)
{
int count;
if (!dict.TryGetValue(element, out count))
return false;
else if (--count == 0)
dict.Remove(element);
else
dict[element] = count;
}
return dict.Count == 0;
}
Keep a tally of each element in the first sequence, then check the second against it. The moment you have one too many in the second sequence you can return false, otherwise if you have nothing left in the dictionary of tallies they are equal, or false if there's any elements left.
Rather than the two O(n log n) sorts of using OrderBy()
followed by the O(n) comparison, you've an O(n) operation building the set of tallies, and an O(n) check against it.