# When comparing two ListT> objects for equality, order [duplicate] is ignored.

## Problem

``````List<MyType> list1;
List<MyType> list2;
``````

Regardless of where they are in the list, I need to double-check that they each have the same elements. On a list, any MyType object might appear several times. Is this something that can be checked using a built-in function? What if I promised that each element would only appear once in a list?

EDIT: Thanks for the responses, but I forgot to include that the number of occurrences of each element on both lists should be the same.

## Solution #1

If you want them to be really equal (i.e. the same items and the same number of each item), I think that the simplest solution is to sort before comparing:

``````Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t))
``````

Here is a solution that performs a bit better (about ten times faster), and only requires IEquatable, not IComparable:

``````public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2) {
var cnt = new Dictionary<T, int>();
foreach (T s in list1) {
if (cnt.ContainsKey(s)) {
cnt[s]++;
} else {
}
}
foreach (T s in list2) {
if (cnt.ContainsKey(s)) {
cnt[s]--;
} else {
return false;
}
}
return cnt.Values.All(c => c == 0);
}
``````

You can construct a version that takes a comparer for the dictionary to handle any data type as a key (for example, nullable types, as Frank Tzanabetis pointed out):

``````public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer) {
var cnt = new Dictionary<T, int>(comparer);
...
``````

## Solution #2

I would tackle it this way if you don’t bothered about the amount of instances. You’ll get better results with hash sets than with plain iteration.

``````var set1 = new HashSet<MyType>(list1);
var set2 = new HashSet<MyType>(list2);
return set1.SetEquals(set2);
``````

This will necessitate the use of override. On MyType, I implemented GetHashCode() and IEquatableMyType>.

## Solution #3

This question is ambiguous in its current form. The following is the statement:

does not specify whether you want the two lists to have the same collection of objects or a different set of things.

If you want to make sure that all of the members in two collections are the same, regardless of order, you can use:

``````// lists should have same count of items, and set difference must be empty
var areEquivalent = (list1.Count == list2.Count) && !list1.Except(list2).Any();
``````

If you want to make sure that two collections have the same set of members (and that duplicates in either are ignored), you can use the following formula:

``````// check that [(A-B) Union (B-A)] is empty
var areEquivalent = !list1.Except(list2).Union( list2.Except(list1) ).Any();
``````

Using the set operations (Intersect, Union, Except) is more efficient than using methods like Contains. In my opinion, it also better expresses the expectations of your query.

EDIT: Now that you’ve explained your query, I can tell you that the first form is the one to use, because duplicates are a problem. Here’s a basic example to show that you can get the desired result:

``````var a = new[] {1, 2, 3, 4, 4, 3, 1, 1, 2};
var b = new[] { 4, 3, 2, 3, 1, 1, 1, 4, 2 };

// result below should be true, since the two sets are equivalent...
var areEquivalent = (a.Count() == b.Count()) && !a.Except(b).Any();
``````

## Solution #4

You might use this alternative in addition to Guffa’s solution to have a more shorthanded notation.

``````public static bool ScrambledEquals<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
{
var deletedItems = list1.Except(list2).Any();
var newItems = list2.Except(list1).Any();
return !newItems && !deletedItems;
}
``````

## Solution #5

This is what I’m thinking will work for you:

``````list1.All(item => list2.Contains(item)) &&
list2.All(item => list1.Contains(item));
``````

If you want to make it stand out, replace it to:

``````list1.All(item => list2.Contains(item)) &&
list1.Distinct().Count() == list1.Count &&
list1.Count == list2.Count
``````