<p>I would like to compare two collections (in C#), but I'm not sure of the best way to implement this efficiently.</p>

<p>I've read the other thread about <a href="https://stackoverflow.com/questions/43500/is-there-a-built-in-method-to-compare-collections-in-c">Enumerable.SequenceEqual</a>, but it's not exactly what I'm looking for.</p>

<p>In my case, two collections would be equal if they both contain the same items (no matter the order).</p>

<p>Example:</p>

<pre><code>collection1 = {1, 2, 3, 4};
collection2 = {2, 4, 1, 3};

collection1 == collection2; // true
</code></pre>

<p>What I usually do is to loop through each item of one collection and see if it exists in the other collection, then loop through each item of the other collection and see if it exists in the first collection. (I start by comparing the lengths).</p>

<pre><code>if (collection1.Count != collection2.Count)
    return false; // the collections are not equal

foreach (Item item in collection1)
{
    if (!collection2.Contains(item))
        return false; // the collections are not equal
}

foreach (Item item in collection2)
{
    if (!collection1.Contains(item))
        return false; // the collections are not equal
}

return true; // the collections are equal
</code></pre>

<p>However, this is not entirely correct, and it's probably not the most efficient way to do compare two collections for equality.</p>

<p>An example I can think of that would be wrong is:</p>

<pre><code>collection1 = {1, 2, 3, 3, 4}
collection2 = {1, 2, 2, 3, 4}
</code></pre>

<p>Which would be equal with my implementation. Should I just count the number of times each item is found and make sure the counts are equal in both collections?</p>

<hr>

<p>The examples are in some sort of C# (let's call it pseudo-C#), but give your answer in whatever language you wish, it does not matter.</p>

<p><strong>Note:</strong> I used integers in the examples for simplicity, but I want to be able to use reference-type objects too (they do not behave correctly as keys because only the reference of the object is compared, not the content).</p>

[{'answer_id': 50154, 'author': 'Daniel Jennings', 'author_id': 3641, 'author_profile': 'https://Stackoverflow.com/users/3641', 'pm_score': 5, 'selected': False, 'text': '<p>Create a Dictionary "dict" and then for each member in the first collection, do dict[member]++;</p>\n\n<p>Then, loop over the second collection in the same way, but for each member do dict[member]--.</p>\n\n<p>At the end, loop over all of the members in the dictionary:</p>\n\n<pre><code>    private bool SetEqual (List&lt;int&gt; left, List&lt;int&gt; right) {\n\n        if (left.Count != right.Count)\n            return false;\n\n        Dictionary&lt;int, int&gt; dict = new Dictionary&lt;int, int&gt;();\n\n        foreach (int member in left) {\n            if (dict.ContainsKey(member) == false)\n                dict[member] = 1;\n            else\n                dict[member]++;\n        }\n\n        foreach (int member in right) {\n            if (dict.ContainsKey(member) == false)\n                return false;\n            else\n                dict[member]--;\n        }\n\n        foreach (KeyValuePair&lt;int, int&gt; kvp in dict) {\n            if (kvp.Value != 0)\n                return false;\n        }\n\n        return true;\n\n    }\n</code></pre>\n\n<p>Edit: As far as I can tell this is on the same order as the most efficient algorithm. This algorithm is O(N), assuming that the Dictionary uses O(1) lookups.</p>\n'}, {'answer_id': 50171, 'author': 'James A. Rosen', 'author_id': 1190, 'author_profile': 'https://Stackoverflow.com/users/1190', 'pm_score': 0, 'selected': False, 'text': '<p><a href="https://stackoverflow.com/users/3474/erickson">erickson</a> is almost right: since you want to match on counts of duplicates, you want a <a href="http://commons.apache.org/collections/api-3.1/org/apache/commons/collections/HashBag.html" rel="nofollow noreferrer">Bag</a>.  In Java, this looks something like:</p>\n\n<pre><code>(new HashBag(collection1)).equals(new HashBag(collection2))\n</code></pre>\n\n<p>I\'m sure C# has a built-in Set implementation.  I would use that first; if performance is a problem, you could always use a different Set implementation, but use the same Set interface.</p>\n'}, {'answer_id': 50177, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 7, 'selected': False, 'text': '<p>A simple and fairly efficient solution is to sort both collections and then compare them for equality:</p>\n\n<pre><code>bool equal = collection1.OrderBy(i =&gt; i).SequenceEqual(\n                 collection2.OrderBy(i =&gt; i));\n</code></pre>\n\n<p>This algorithm is O(N*logN), while your solution above is O(N^2).</p>\n\n<p>If the collections have certain properties, you may be able to implement a faster solution. For example, if both of your collections are hash sets, they cannot contain duplicates. Also, checking whether a hash set contains some element is very fast. In that case an algorithm similar to yours would likely be fastest.</p>\n'}, {'answer_id': 50465, 'author': 'mbillard', 'author_id': 810, 'author_profile': 'https://Stackoverflow.com/users/810', 'pm_score': 4, 'selected': False, 'text': '<p>This is my (heavily influenced by D.Jennings) generic implementation of the comparison method (in C#):</p>\n\n<pre><code>/// &lt;summary&gt;\n/// Represents a service used to compare two collections for equality.\n/// &lt;/summary&gt;\n/// &lt;typeparam name="T"&gt;The type of the items in the collections.&lt;/typeparam&gt;\npublic class CollectionComparer&lt;T&gt;\n{\n    /// &lt;summary&gt;\n    /// Compares the content of two collections for equality.\n    /// &lt;/summary&gt;\n    /// &lt;param name="foo"&gt;The first collection.&lt;/param&gt;\n    /// &lt;param name="bar"&gt;The second collection.&lt;/param&gt;\n    /// &lt;returns&gt;True if both collections have the same content, false otherwise.&lt;/returns&gt;\n    public bool Execute(ICollection&lt;T&gt; foo, ICollection&lt;T&gt; bar)\n    {\n        // Declare a dictionary to count the occurence of the items in the collection\n        Dictionary&lt;T, int&gt; itemCounts = new Dictionary&lt;T,int&gt;();\n\n        // Increase the count for each occurence of the item in the first collection\n        foreach (T item in foo)\n        {\n            if (itemCounts.ContainsKey(item))\n            {\n                itemCounts[item]++;\n            }\n            else\n            {\n                itemCounts[item] = 1;\n            }\n        }\n\n        // Wrap the keys in a searchable list\n        List&lt;T&gt; keys = new List&lt;T&gt;(itemCounts.Keys);\n\n        // Decrease the count for each occurence of the item in the second collection\n        foreach (T item in bar)\n        {\n            // Try to find a key for the item\n            // The keys of a dictionary are compared by reference, so we have to\n            // find the original key that is equivalent to the "item"\n            // You may want to override ".Equals" to define what it means for\n            // two "T" objects to be equal\n            T key = keys.Find(\n                delegate(T listKey)\n                {\n                    return listKey.Equals(item);\n                });\n\n            // Check if a key was found\n            if(key != null)\n            {\n                itemCounts[key]--;\n            }\n            else\n            {\n                // There was no occurence of this item in the first collection, thus the collections are not equal\n                return false;\n            }\n        }\n\n        // The count of each item should be 0 if the contents of the collections are equal\n        foreach (int value in itemCounts.Values)\n        {\n            if (value != 0)\n            {\n                return false;\n            }\n        }\n\n        // The collections are equal\n        return true;\n    }\n}\n</code></pre>\n'}, {'answer_id': 169748, 'author': 'Joel Gauvreau', 'author_id': 4789, 'author_profile': 'https://Stackoverflow.com/users/4789', 'pm_score': 4, 'selected': False, 'text': '<p>You could use a <a href="http://msdn.microsoft.com/en-us/library/bb359438.aspx" rel="noreferrer">Hashset</a>.  Look at the <a href="http://msdn.microsoft.com/en-us/library/bb346516.aspx" rel="noreferrer">SetEquals</a> method.</p>\n'}, {'answer_id': 194566, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': "<p>There are many solutions to this problem. \nIf you don't care about duplicates, you don't have to sort both. First make sure that they have the same number of items. After that sort one of the collections. Then binsearch each item from the second collection in the sorted collection. If you don't find a given item stop and return false.\nThe complexity of this:\n- sorting the first collection: N<em>Log(N)\n- searching each item from second into the first: N</em>LOG(N)\nso you end up with 2*N*LOG(N) assuming that they match and you look up everything. This is similar to the complexity of sorting both. Also this gives you the benefit to stop earlier if there's a difference.\nHowever, keep in mind that if both are sorted before you step into this comparison and you try sorting by use something like a qsort, the sorting will be more expensive. There are optimizations for this.\nAnother alternative, which is great for small collections where you know the range of the elements is to use a bitmask index. This will give you a O(n) performance.\nAnother alternative is to use a hash and look it up. For small collections it is usually a lot better to do the sorting or the bitmask index. Hashtable have the disadvantage of worse locality so keep that in mind.\nAgain, that's only if you don't care about duplicates. If you want to account for duplicates go with sorting both.</p>\n"}, {'answer_id': 1015692, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 3, 'selected': False, 'text': '<p>EDIT: I realized as soon as I posed that this really only works for sets -- it will not properly deal with collections that have duplicate items.  For example { 1, 1, 2 } and { 2, 2, 1 } will be considered equal from this algorithm\'s perspective.  If your collections are sets (or their equality can be measured that way), however, I hope you find the below useful.</p>\n\n<p>The solution I use is:</p>\n\n<pre><code>return c1.Count == c2.Count &amp;&amp; c1.Intersect(c2).Count() == c1.Count;\n</code></pre>\n\n<p>Linq does the dictionary thing under the covers, so this is also O(N).  (Note, it\'s O(1) if the collections aren\'t the same size).</p>\n\n<p>I did a sanity check using the "SetEqual" method suggested by Daniel, the OrderBy/SequenceEquals method suggested by Igor, and my suggestion.  The results are below, showing O(N*LogN) for Igor and O(N) for mine and Daniel\'s.</p>\n\n<p>I think the simplicity of the Linq intersect code makes it the preferable solution.</p>\n\n<pre><code>__Test Latency(ms)__\nN, SetEquals, OrderBy, Intersect    \n1024, 0, 0, 0    \n2048, 0, 0, 0    \n4096, 31.2468, 0, 0    \n8192, 62.4936, 0, 0    \n16384, 156.234, 15.6234, 0    \n32768, 312.468, 15.6234, 46.8702    \n65536, 640.5594, 46.8702, 31.2468    \n131072, 1312.3656, 93.7404, 203.1042    \n262144, 3765.2394, 187.4808, 187.4808    \n524288, 5718.1644, 374.9616, 406.2084    \n1048576, 11420.7054, 734.2998, 718.6764    \n2097152, 35090.1564, 1515.4698, 1484.223\n</code></pre>\n'}, {'answer_id': 2564351, 'author': 'Ohad Schneider', 'author_id': 67824, 'author_profile': 'https://Stackoverflow.com/users/67824', 'pm_score': 3, 'selected': False, 'text': '<p>In the case of no repeats and no order, the following EqualityComparer can be used to allow collections as dictionary keys:</p>\n\n<pre><code>public class SetComparer&lt;T&gt; : IEqualityComparer&lt;IEnumerable&lt;T&gt;&gt; \nwhere T:IComparable&lt;T&gt;\n{\n    public bool Equals(IEnumerable&lt;T&gt; first, IEnumerable&lt;T&gt; second)\n    {\n        if (first == second)\n            return true;\n        if ((first == null) || (second == null))\n            return false;\n        return first.ToHashSet().SetEquals(second);\n    }\n\n    public int GetHashCode(IEnumerable&lt;T&gt; enumerable)\n    {\n        int hash = 17;\n\n        foreach (T val in enumerable.OrderBy(x =&gt; x))\n            hash = hash * 23 + val.GetHashCode();\n\n        return hash;\n    }\n}\n</code></pre>\n\n<p><a href="http://team.pushbomb.com/2008/09/08/the_fastest_dot_net_hash_set_collection_with_linq_extended_features/" rel="nofollow noreferrer">Here</a> is the ToHashSet() implementation I used. The <a href="https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode/263416#263416">hash code algorithm</a> comes from Effective Java (by way of Jon Skeet). </p>\n'}, {'answer_id': 2740602, 'author': 'user329244', 'author_id': 329244, 'author_profile': 'https://Stackoverflow.com/users/329244', 'pm_score': 2, 'selected': False, 'text': '<p>A duplicate post of sorts, but <a href="http://robertbouillon.com/2010/04/29/comparing-collections-in-net/" rel="nofollow noreferrer">check out my solution for comparing collections</a>. It\'s pretty simple:</p>\n\n<p>This will perform an equality comparison regardless of order:</p>\n\n<pre><code>var list1 = new[] { "Bill", "Bob", "Sally" };\nvar list2 = new[] { "Bob", "Bill", "Sally" };\nbool isequal = list1.Compare(list2).IsSame;\n</code></pre>\n\n<p>This will check to see if items were added / removed:</p>\n\n<pre><code>var list1 = new[] { "Billy", "Bob" };\nvar list2 = new[] { "Bob", "Sally" };\nvar diff = list1.Compare(list2);\nvar onlyinlist1 = diff.Removed; //Billy\nvar onlyinlist2 = diff.Added;   //Sally\nvar inbothlists = diff.Equal;   //Bob\n</code></pre>\n\n<p>This will see what items in the dictionary changed:</p>\n\n<pre><code>var original = new Dictionary&lt;int, string&gt;() { { 1, "a" }, { 2, "b" } };\nvar changed = new Dictionary&lt;int, string&gt;() { { 1, "aaa" }, { 2, "b" } };\nvar diff = original.Compare(changed, (x, y) =&gt; x.Value == y.Value, (x, y) =&gt; x.Value == y.Value);\nforeach (var item in diff.Different)\n  Console.Write("{0} changed to {1}", item.Key.Value, item.Value.Value);\n//Will output: a changed to aaa\n</code></pre>\n\n<p>Original post <a href="https://stackoverflow.com/questions/43500/is-there-a-built-in-method-to-compare-collections-in-c/2740552#2740552">here</a>.</p>\n'}, {'answer_id': 3790621, 'author': 'Ohad Schneider', 'author_id': 67824, 'author_profile': 'https://Stackoverflow.com/users/67824', 'pm_score': 8, 'selected': True, 'text': '<p>It turns out Microsoft already has this covered in its testing framework: <a href="http://msdn.microsoft.com/en-us/library/ms243779.aspx" rel="noreferrer">CollectionAssert.AreEquivalent</a></p>\n<blockquote>\n<p>Remarks</p>\n<p>Two collections are equivalent if they\nhave the same elements in the same\nquantity, but in any order. Elements\nare equal if their values are equal,\nnot if they refer to the same object.</p>\n</blockquote>\n<p>Using reflector, I modified the code behind AreEquivalent() to create a corresponding equality comparer. It is more complete than existing answers, since it takes nulls into account, implements IEqualityComparer and has some efficiency and edge case checks. plus, it\'s <em>Microsoft</em> :)</p>\n<pre><code>public class MultiSetComparer&lt;T&gt; : IEqualityComparer&lt;IEnumerable&lt;T&gt;&gt;\n{\n    private readonly IEqualityComparer&lt;T&gt; m_comparer;\n    public MultiSetComparer(IEqualityComparer&lt;T&gt; comparer = null)\n    {\n        m_comparer = comparer ?? EqualityComparer&lt;T&gt;.Default;\n    }\n\n    public bool Equals(IEnumerable&lt;T&gt; first, IEnumerable&lt;T&gt; second)\n    {\n        if (first == null)\n            return second == null;\n\n        if (second == null)\n            return false;\n\n        if (ReferenceEquals(first, second))\n            return true;\n\n        if (first is ICollection&lt;T&gt; firstCollection &amp;&amp; second is ICollection&lt;T&gt; secondCollection)\n        {\n            if (firstCollection.Count != secondCollection.Count)\n                return false;\n\n            if (firstCollection.Count == 0)\n                return true;\n        }\n\n        return !HaveMismatchedElement(first, second);\n    }\n\n    private bool HaveMismatchedElement(IEnumerable&lt;T&gt; first, IEnumerable&lt;T&gt; second)\n    {\n        int firstNullCount;\n        int secondNullCount;\n\n        var firstElementCounts = GetElementCounts(first, out firstNullCount);\n        var secondElementCounts = GetElementCounts(second, out secondNullCount);\n\n        if (firstNullCount != secondNullCount || firstElementCounts.Count != secondElementCounts.Count)\n            return true;\n\n        foreach (var kvp in firstElementCounts)\n        {\n            var firstElementCount = kvp.Value;\n            int secondElementCount;\n            secondElementCounts.TryGetValue(kvp.Key, out secondElementCount);\n\n            if (firstElementCount != secondElementCount)\n                return true;\n        }\n\n        return false;\n    }\n\n    private Dictionary&lt;T, int&gt; GetElementCounts(IEnumerable&lt;T&gt; enumerable, out int nullCount)\n    {\n        var dictionary = new Dictionary&lt;T, int&gt;(m_comparer);\n        nullCount = 0;\n\n        foreach (T element in enumerable)\n        {\n            if (element == null)\n            {\n                nullCount++;\n            }\n            else\n            {\n                int num;\n                dictionary.TryGetValue(element, out num);\n                num++;\n                dictionary[element] = num;\n            }\n        }\n\n        return dictionary;\n    }\n\n    public int GetHashCode(IEnumerable&lt;T&gt; enumerable)\n    {\n        if (enumerable == null) throw new \n            ArgumentNullException(nameof(enumerable));\n\n        int hash = 17;\n\n        foreach (T val in enumerable)\n            hash ^= (val == null ? 42 : m_comparer.GetHashCode(val));\n\n        return hash;\n    }\n}\n</code></pre>\n<p>Sample usage:</p>\n<pre><code>var set = new HashSet&lt;IEnumerable&lt;int&gt;&gt;(new[] {new[]{1,2,3}}, new MultiSetComparer&lt;int&gt;());\nConsole.WriteLine(set.Contains(new [] {3,2,1})); //true\nConsole.WriteLine(set.Contains(new [] {1, 2, 3, 3})); //false\n</code></pre>\n<p>Or if you just want to compare two collections directly:</p>\n<pre><code>var comp = new MultiSetComparer&lt;string&gt;();\nConsole.WriteLine(comp.Equals(new[] {&quot;a&quot;,&quot;b&quot;,&quot;c&quot;}, new[] {&quot;a&quot;,&quot;c&quot;,&quot;b&quot;})); //true\nConsole.WriteLine(comp.Equals(new[] {&quot;a&quot;,&quot;b&quot;,&quot;c&quot;}, new[] {&quot;a&quot;,&quot;b&quot;})); //false\n</code></pre>\n<p>Finally, you can use your an equality comparer of your choice:</p>\n<pre><code>var strcomp = new MultiSetComparer&lt;string&gt;(StringComparer.OrdinalIgnoreCase);\nConsole.WriteLine(strcomp.Equals(new[] {&quot;a&quot;, &quot;b&quot;}, new []{&quot;B&quot;, &quot;A&quot;})); //true\n</code></pre>\n'}, {'answer_id': 6985006, 'author': 'Korayem', 'author_id': 80434, 'author_profile': 'https://Stackoverflow.com/users/80434', 'pm_score': 2, 'selected': False, 'text': '<p>Why not use .Except()</p>\n\n<pre><code>// Create the IEnumerable data sources.\nstring[] names1 = System.IO.File.ReadAllLines(@"../../../names1.txt");\nstring[] names2 = System.IO.File.ReadAllLines(@"../../../names2.txt");\n// Create the query. Note that method syntax must be used here.\nIEnumerable&lt;string&gt; differenceQuery =   names1.Except(names2);\n// Execute the query.\nConsole.WriteLine("The following lines are in names1.txt but not names2.txt");\nforeach (string s in differenceQuery)\n     Console.WriteLine(s);\n</code></pre>\n\n<p><a href="http://msdn.microsoft.com/en-us/library/bb397894.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/bb397894.aspx</a></p>\n'}, {'answer_id': 9658866, 'author': 'Eric J.', 'author_id': 141172, 'author_profile': 'https://Stackoverflow.com/users/141172', 'pm_score': 1, 'selected': False, 'text': "<p>Here's my extension method variant of ohadsc's answer, in case it's useful to someone</p>\n\n<pre><code>static public class EnumerableExtensions \n{\n    static public bool IsEquivalentTo&lt;T&gt;(this IEnumerable&lt;T&gt; first, IEnumerable&lt;T&gt; second)\n    {\n        if ((first == null) != (second == null))\n            return false;\n\n        if (!object.ReferenceEquals(first, second) &amp;&amp; (first != null))\n        {\n            if (first.Count() != second.Count())\n                return false;\n\n            if ((first.Count() != 0) &amp;&amp; HaveMismatchedElement&lt;T&gt;(first, second))\n                return false;\n        }\n\n        return true;\n    }\n\n    private static bool HaveMismatchedElement&lt;T&gt;(IEnumerable&lt;T&gt; first, IEnumerable&lt;T&gt; second)\n    {\n        int firstCount;\n        int secondCount;\n\n        var firstElementCounts = GetElementCounts&lt;T&gt;(first, out firstCount);\n        var secondElementCounts = GetElementCounts&lt;T&gt;(second, out secondCount);\n\n        if (firstCount != secondCount)\n            return true;\n\n        foreach (var kvp in firstElementCounts)\n        {\n            firstCount = kvp.Value;\n            secondElementCounts.TryGetValue(kvp.Key, out secondCount);\n\n            if (firstCount != secondCount)\n                return true;\n        }\n\n        return false;\n    }\n\n    private static Dictionary&lt;T, int&gt; GetElementCounts&lt;T&gt;(IEnumerable&lt;T&gt; enumerable, out int nullCount)\n    {\n        var dictionary = new Dictionary&lt;T, int&gt;();\n        nullCount = 0;\n\n        foreach (T element in enumerable)\n        {\n            if (element == null)\n            {\n                nullCount++;\n            }\n            else\n            {\n                int num;\n                dictionary.TryGetValue(element, out num);\n                num++;\n                dictionary[element] = num;\n            }\n        }\n\n        return dictionary;\n    }\n\n    static private int GetHashCode&lt;T&gt;(IEnumerable&lt;T&gt; enumerable)\n    {\n        int hash = 17;\n\n        foreach (T val in enumerable.OrderBy(x =&gt; x))\n            hash = hash * 23 + val.GetHashCode();\n\n        return hash;\n    }\n}\n</code></pre>\n"}, {'answer_id': 18542880, 'author': 'James Roeiter', 'author_id': 1135393, 'author_profile': 'https://Stackoverflow.com/users/1135393', 'pm_score': 0, 'selected': False, 'text': '<p>In many cases the only suitable answer is the one of Igor Ostrovsky , other answers are based on objects hash code. \nBut when you generate an hash code for an object you do so only based on his IMMUTABLE fields - such as object Id field (in case of a database entity) -\n<a href="https://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overridden">Why is it important to override GetHashCode when Equals method is overridden?</a></p>\n\n<p>This means , that if you compare two collections , the result might be true of the compare method even though the fields of the different items are non-equal . \nTo deep compare collections , you need to use Igor\'s method and implement IEqualirity .</p>\n\n<p>Please read the comments of me and mr.Schnider\'s on his most voted post.</p>\n\n<p>James</p>\n'}, {'answer_id': 38003867, 'author': 'palswim', 'author_id': 393280, 'author_profile': 'https://Stackoverflow.com/users/393280', 'pm_score': 3, 'selected': False, 'text': '<pre><code>static bool SetsContainSameElements&lt;T&gt;(IEnumerable&lt;T&gt; set1, IEnumerable&lt;T&gt; set2) {\n    var setXOR = new HashSet&lt;T&gt;(set1);\n    setXOR.SymmetricExceptWith(set2);\n    return (setXOR.Count == 0);\n}\n</code></pre>\n\n<p>Solution requires .NET 3.5 and the <code>System.Collections.Generic</code> namespace. <a href="https://msdn.microsoft.com/en-us/library/bb336848.aspx" rel="noreferrer">According to Microsoft</a>, <code>SymmetricExceptWith</code> is an <em>O(n + m)</em> operation, with <em>n</em> representing the number of elements in the first set and <em>m</em> representing the number of elements in the second. You could always add an equality comparer to this function if necessary.</p>\n'}, {'answer_id': 44248556, 'author': 'N73k', 'author_id': 4379238, 'author_profile': 'https://Stackoverflow.com/users/4379238', 'pm_score': 1, 'selected': False, 'text': '<p>Here is a solution which is an improvement over <a href="https://stackoverflow.com/questions/4042101/net-check-if-two-ienumerablet-have-the-same-elements">this one</a>.</p>\n\n<pre><code>public static bool HasSameElementsAs&lt;T&gt;(\n        this IEnumerable&lt;T&gt; first, \n        IEnumerable&lt;T&gt; second, \n        IEqualityComparer&lt;T&gt; comparer = null)\n    {\n        var firstMap = first\n            .GroupBy(x =&gt; x, comparer)\n            .ToDictionary(x =&gt; x.Key, x =&gt; x.Count(), comparer);\n\n        var secondMap = second\n            .GroupBy(x =&gt; x, comparer)\n            .ToDictionary(x =&gt; x.Key, x =&gt; x.Count(), comparer);\n\n        if (firstMap.Keys.Count != secondMap.Keys.Count)\n            return false;\n\n        if (firstMap.Keys.Any(k1 =&gt; !secondMap.ContainsKey(k1)))\n            return false;\n\n        return firstMap.Keys.All(x =&gt; firstMap[x] == secondMap[x]);\n    }\n</code></pre>\n'}, {'answer_id': 47289089, 'author': 'Pier-Lionel Sgard', 'author_id': 8500879, 'author_profile': 'https://Stackoverflow.com/users/8500879', 'pm_score': 3, 'selected': False, 'text': '<p>If you use <a href="https://shouldly.readthedocs.io" rel="noreferrer">Shouldly</a>, you can use ShouldAllBe with Contains.\n</p>\n\n<pre><code>collection1 = {1, 2, 3, 4};\ncollection2 = {2, 4, 1, 3};\n\ncollection1.ShouldAllBe(item=&gt;collection2.Contains(item)); // true\n</code></pre>\n\n<p>And finally, you can write an extension.\n</p>\n\n<pre><code>public static class ShouldlyIEnumerableExtensions\n{\n    public static void ShouldEquivalentTo&lt;T&gt;(this IEnumerable&lt;T&gt; list, IEnumerable&lt;T&gt; equivalent)\n    {\n        list.ShouldAllBe(l =&gt; equivalent.Contains(l));\n    }\n}\n</code></pre>\n\n<p><strong>UPDATE</strong></p>\n\n<p>A optional parameter exists on <strong>ShouldBe</strong> method.</p>\n\n<pre class="lang-cs prettyprint-override"><code>collection1.ShouldBe(collection2, ignoreOrder: true); // true\n</code></pre>\n'}, {'answer_id': 51775026, 'author': 'Josh Gust', 'author_id': 4629442, 'author_profile': 'https://Stackoverflow.com/users/4629442', 'pm_score': 0, 'selected': False, 'text': '<p>Allowing for duplicates in the <code>IEnumerable&lt;T&gt;</code> (if sets are not desirable\\possible) and "ignoring order" you should be able to use a <code>.GroupBy()</code>. </p>\n\n<p>I\'m not an expert on the complexity measurements, but my rudimentary understanding is that this should be O(n). I understand O(n^2) as coming from performing an O(n) operation inside another O(n) operation like <code>ListA.Where(a =&gt; ListB.Contains(a)).ToList()</code>. Every item in ListB is evaluated for equality against each item in ListA.</p>\n\n<p>Like I said, my understanding on complexity is limited, so correct me on this if I\'m wrong. </p>\n\n<pre><code>public static bool IsSameAs&lt;T, TKey&gt;(this IEnumerable&lt;T&gt; source, IEnumerable&lt;T&gt; target, Expression&lt;Func&lt;T, TKey&gt;&gt; keySelectorExpression)\n    {\n        // check the object\n        if (source == null &amp;&amp; target == null) return true;\n        if (source == null || target == null) return false;\n\n        var sourceList = source.ToList();\n        var targetList = target.ToList();\n\n        // check the list count :: { 1,1,1 } != { 1,1,1,1 }\n        if (sourceList.Count != targetList.Count) return false;\n\n        var keySelector = keySelectorExpression.Compile();\n        var groupedSourceList = sourceList.GroupBy(keySelector).ToList();\n        var groupedTargetList = targetList.GroupBy(keySelector).ToList();\n\n        // check that the number of grouptings match :: { 1,1,2,3,4 } != { 1,1,2,3,4,5 }\n        var groupCountIsSame = groupedSourceList.Count == groupedTargetList.Count;\n        if (!groupCountIsSame) return false;\n\n        // check that the count of each group in source has the same count in target :: for values { 1,1,2,3,4 } &amp; { 1,1,1,2,3,4 }\n        // key:count\n        // { 1:2, 2:1, 3:1, 4:1 } != { 1:3, 2:1, 3:1, 4:1 }\n        var countsMissmatch = groupedSourceList.Any(sourceGroup =&gt;\n                                                        {\n                                                            var targetGroup = groupedTargetList.Single(y =&gt; y.Key.Equals(sourceGroup.Key));\n                                                            return sourceGroup.Count() != targetGroup.Count();\n                                                        });\n        return !countsMissmatch;\n    }\n</code></pre>\n'}, {'answer_id': 53857873, 'author': 'Jo Ham', 'author_id': 4348580, 'author_profile': 'https://Stackoverflow.com/users/4348580', 'pm_score': 0, 'selected': False, 'text': '<p><a href="https://stackoverflow.com/a/50177/4348580">This simple solution</a> forces the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1" rel="nofollow noreferrer"><code>IEnumerable</code></a>\'s generic type to implement <a href="https://learn.microsoft.com/en-us/dotnet/api/system.icomparable" rel="nofollow noreferrer"><code>IComparable</code></a>. Because of \n<a href="https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby#System_Linq_Enumerable_OrderBy__2_System_Collections_Generic_IEnumerable___0__System_Func___0___1__" rel="nofollow noreferrer"><code>OrderBy</code></a>\'s definition.</p>\n\n<p>If you don\'t want to make such an assumption but still want use this solution, you can use the following piece of code : </p>\n\n<pre><code>bool equal = collection1.OrderBy(i =&gt; i?.GetHashCode())\n   .SequenceEqual(collection2.OrderBy(i =&gt; i?.GetHashCode()));\n</code></pre>\n'}, {'answer_id': 57664570, 'author': 'crokusek', 'author_id': 538763, 'author_profile': 'https://Stackoverflow.com/users/538763', 'pm_score': 0, 'selected': False, 'text': '<p>If comparing for the purpose of Unit Testing Assertions, it may make sense to throw some efficiency out the window and simply convert each list to a string representation (csv) before doing the comparison.  That way, the default test Assertion message will display the differences within the error message.</p>\n\n<p>Usage:</p>\n\n<pre><code>using Microsoft.VisualStudio.TestTools.UnitTesting;\n\n// define collection1, collection2, ...\n\nAssert.Equal(collection1.OrderBy(c=&gt;c).ToCsv(), collection2.OrderBy(c=&gt;c).ToCsv());\n</code></pre>\n\n<p>Helper Extension Method:</p>\n\n<pre><code>public static string ToCsv&lt;T&gt;(\n    this IEnumerable&lt;T&gt; values,\n    Func&lt;T, string&gt; selector,\n    string joinSeparator = ",")\n{\n    if (selector == null)\n    {\n        if (typeof(T) == typeof(Int16) ||\n            typeof(T) == typeof(Int32) ||\n            typeof(T) == typeof(Int64))\n        {\n            selector = (v) =&gt; Convert.ToInt64(v).ToStringInvariant();\n        }\n        else if (typeof(T) == typeof(decimal))\n        {\n            selector = (v) =&gt; Convert.ToDecimal(v).ToStringInvariant();\n        }\n        else if (typeof(T) == typeof(float) ||\n                typeof(T) == typeof(double))\n        {\n            selector = (v) =&gt; Convert.ToDouble(v).ToString(CultureInfo.InvariantCulture);\n        }\n        else\n        {\n            selector = (v) =&gt; v.ToString();\n        }\n    }\n\n    return String.Join(joinSeparator, values.Select(v =&gt; selector(v)));\n}\n</code></pre>\n'}, {'answer_id': 67486151, 'author': 'xhafan', 'author_id': 379279, 'author_profile': 'https://Stackoverflow.com/users/379279', 'pm_score': 1, 'selected': False, 'text': '<p>Based on this <a href="https://stackoverflow.com/a/3670082/379279">answer</a> of a duplicate question, and the comments below the answer, and @brian-genisio <a href="https://stackoverflow.com/a/3669985/379279">answer</a> I came up with these:</p>\n<pre><code>        public static bool AreEquivalentIgnoringDuplicates&lt;T&gt;(this IEnumerable&lt;T&gt; items, IEnumerable&lt;T&gt; otherItems)\n        {\n            var itemList = items.ToList();\n            var otherItemList = otherItems.ToList();\n            var except = itemList.Except(otherItemList);\n            return itemList.Count == otherItemList.Count &amp;&amp; except.IsEmpty();\n        }\n\n        public static bool AreEquivalent&lt;T&gt;(this IEnumerable&lt;T&gt; items, IEnumerable&lt;T&gt; otherItems)\n        {\n            var itemList = items.ToList();\n            var otherItemList = otherItems.ToList();\n            var except = itemList.Except(otherItemList);\n            return itemList.Distinct().Count() == otherItemList.Count &amp;&amp; except.IsEmpty();\n        }\n</code></pre>\n<p>Tests for these two:</p>\n<pre><code>        [Test]\n        public void collection_with_duplicates_are_equivalent()\n        {\n            var a = new[] {1, 5, 5};\n            var b = new[] {1, 1, 5};\n\n            a.AreEquivalentIgnoringDuplicates(b).ShouldBe(true); \n        }\n\n        [Test]\n        public void collection_with_duplicates_are_not_equivalent()\n        {\n            var a = new[] {1, 5, 5};\n            var b = new[] {1, 1, 5};\n\n            a.AreEquivalent(b).ShouldBe(false); \n        }\n</code></pre>\n'}, {'answer_id': 72801254, 'author': 'Adam Simon', 'author_id': 8656352, 'author_profile': 'https://Stackoverflow.com/users/8656352', 'pm_score': 0, 'selected': False, 'text': '<p>Here\'s my stab at the problem. It\'s based on <a href="https://stackoverflow.com/a/50154/8656352">this strategy</a> but also borrows some ideas from <a href="https://stackoverflow.com/a/3790621/8656352">the accepted answer</a>.</p>\n<pre><code>public static class EnumerableExtensions\n{\n    public static bool SequenceEqualUnordered&lt;TSource&gt;(this IEnumerable&lt;TSource&gt; source, IEnumerable&lt;TSource&gt; second)\n    {\n        return SequenceEqualUnordered(source, second, EqualityComparer&lt;TSource&gt;.Default);\n    }\n   \n    public static bool SequenceEqualUnordered&lt;TSource&gt;(this IEnumerable&lt;TSource&gt; source, IEnumerable&lt;TSource&gt; second, IEqualityComparer&lt;TSource&gt; comparer)\n    {\n        if (source == null)\n            throw new ArgumentNullException(nameof(source));\n\n        if (second == null)\n            throw new ArgumentNullException(nameof(second));\n\n        if (source.TryGetCount(out int firstCount) &amp;&amp; second.TryGetCount(out int secondCount))\n        {\n            if (firstCount != secondCount)\n                return false;\n\n            if (firstCount == 0)\n                return true;\n        }\n\n        IEqualityComparer&lt;ValueTuple&lt;TSource&gt;&gt; wrapperComparer = comparer != null ? new WrappedItemComparer&lt;TSource&gt;(comparer) : null;\n\n        Dictionary&lt;ValueTuple&lt;TSource&gt;, int&gt; counters;\n        ValueTuple&lt;TSource&gt; key;\n        int counter;\n\n        using (IEnumerator&lt;TSource&gt; enumerator = source.GetEnumerator())\n        {\n            if (!enumerator.MoveNext())\n                return !second.Any();\n\n            counters = new Dictionary&lt;ValueTuple&lt;TSource&gt;, int&gt;(wrapperComparer);\n\n            do\n            {\n                key = new ValueTuple&lt;TSource&gt;(enumerator.Current);\n\n                if (counters.TryGetValue(key, out counter))\n                    counters[key] = counter + 1;\n                else\n                    counters.Add(key, 1);\n            }\n            while (enumerator.MoveNext());\n        }\n\n        foreach (TSource item in second)\n        {\n            key = new ValueTuple&lt;TSource&gt;(item);\n\n            if (counters.TryGetValue(key, out counter))\n            {\n                if (counter &lt;= 0)\n                    return false;\n\n                counters[key] = counter - 1;\n            }\n            else\n                return false;\n        }\n\n        return counters.Values.All(cnt =&gt; cnt == 0);\n    }\n\n    private static bool TryGetCount&lt;TSource&gt;(this IEnumerable&lt;TSource&gt; source, out int count)\n    {\n        switch (source)\n        {\n            case ICollection&lt;TSource&gt; collection:\n                count = collection.Count;\n                return true;\n            case IReadOnlyCollection&lt;TSource&gt; readOnlyCollection:\n                count = readOnlyCollection.Count;\n                return true;\n            case ICollection nonGenericCollection:\n                count = nonGenericCollection.Count;\n                return true;\n            default:\n                count = default;\n                return false;\n        }\n    }\n\n    private sealed class WrappedItemComparer&lt;TSource&gt; : IEqualityComparer&lt;ValueTuple&lt;TSource&gt;&gt;\n    {\n        private readonly IEqualityComparer&lt;TSource&gt; _comparer;\n\n        public WrappedItemComparer(IEqualityComparer&lt;TSource&gt; comparer)\n        {\n            _comparer = comparer;\n        }\n\n        public bool Equals(ValueTuple&lt;TSource&gt; x, ValueTuple&lt;TSource&gt; y) =&gt; _comparer.Equals(x.Item1, y.Item1);\n\n        public int GetHashCode(ValueTuple&lt;TSource&gt; obj) =&gt; _comparer.GetHashCode(obj.Item1);\n    }\n}\n</code></pre>\n<p>Improvements on the MS solution:</p>\n<ul>\n<li>Doesn\'t take the <code>ReferenceEquals(first, second)</code> shortcut because it\'s kind of debatable. For example, consider a custom <code>IEnumerable&lt;T&gt;</code> which has an implementation like this: <code>public IEnumerator&lt;T&gt; GetEnumerator() =&gt; Enumerable.Repeat(default(T), new Random().Next(10)).GetEnumerator()</code>.</li>\n<li>Takes possible shortcuts when both enumerable is a collection but checks not only for <code>ICollection&lt;T&gt;</code> but also for other collection interfaces.</li>\n<li>Handles null values properly. Counting null values separately from the other (non-null) values also doesn\'t look 100% fail-safe. Consider a custom equality comparer which handles null values in a non-standard way.</li>\n</ul>\n<p>This solution is also available in my <a href="https://www.nuget.org/packages/Karambolo.Common" rel="nofollow noreferrer">utility NuGet package</a>.</p>\n'}]
['https://Stackoverflow.com/questions/50098', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/810/']