Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by DylanST · Feb 01, 2017 at 03:41 AM · c#listscompare

How do I compare two lists for equality (not caring about order) C#

I have two lists and I want them to be checked to see if they have the same elements. I also want to ignore the order of the two lists. I just want it to check if they contain the same values.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

6 Replies

· Add your reply
  • Sort: 
avatar image
4
Best Answer

Answer by Bunny83 · Feb 02, 2017 at 05:47 AM

Since we have now many implementations that have a complexity of O(n²), i'll post the one i mentioned in the comment above.

 public static bool CompareLists<T>(List<T> aListA, List<T> aListB)
 {
     if (aListA == null || aListB == null || aListA.Count != aListB.Count)
         return false;
     if (aListA.Count == 0)
         return true;

     Dictionary<T, int> lookUp = new Dictionary<T, int>();
     // create index for the first list
     for(int i = 0; i < aListA.Count; i++)
     {
         int count = 0;
         if (!lookUp.TryGetValue(aListA[i], out count))
         {
             lookUp.Add(aListA[i], 1);
             continue;
         }
         lookUp[aListA[i]] = count + 1;
     }

     for (int i = 0; i < aListB.Count; i++)
     {
         int count = 0;
         if (!lookUp.TryGetValue(aListB[i], out count))
         {
             // early exit as the current value in B doesn't exist in the lookUp (and not in ListA)
             return false;
         }
         count--;
         if (count <= 0)
             lookUp.Remove(aListB[i]);
         else
             lookUp[aListB[i]] = count;
     }
     // if there are remaining elements in the lookUp, that means ListA contains elements that do not exist in ListB
     return lookUp.Count == 0;
 }

This has a linear complexity (O(n) or if you prefer O(2n) but that's actually pointless). A dictionary lookup has a constant complexity (O(1)). So the overall performance of this method should grow linearly with the number of elements.

"List.Contains" has a complexity of O(n). In most of the other solutions here you would execute List.Contains "n"-times so you get a quadratic complexity (O(n²))

If you have trouble understanding what's happening, here are some explanations:

  • First we do an early exit if one (or both) of the lists is null or if they have a different element count. In this case the lists can't be "equal". We don't consider the case when both lists are null as "equal".

  • The second early exit is a special case when both lists exist, but are empty. This is considered "equal".

  • The first loop will iterate through all elements in ListA and check if that element is already in the dictionary. If it is, we simply increase the value that is stored in the dictionary and update the value in the dictionary. If it isn't yet in the dictionary, we add it with a count of 1

  • After the first loop we have a dictionary of all elements of ListA without duplicates.

  • The second loop iterates over all elements in ListB. It again checks if the element exists in the dictionary. However this time if it doesn't exist, we just found an element in ListB that doesn't exist in ListA. If the element is found in the dictionary we decrease the counter for that element by 1. If the counter hits "0" we "used up" all elements of that type and we remove it from the dictionary. Otherwise we simply update the counter for that element.

  • If all items in ListA exist in ListB we should have matched all elements properly and the counter for each element type should have reached "0". Since we removed elements that have reached "0" the Dictionary should be empty at the end. If it is empty then ListA and ListB contains the same elements. If there are elements remaining, some elements from ListA are missing in ListB

As an example

 List<int> A = new List<int>(new int[] { 1, 5, 6, 7, 3, 1 });
 List<int> B = new List<int>(new int[] { 6, 3, 5, 1, 1, 7 });
 if (CompareLists(A, B))
     Debug.Log("Equal");
 else
     Debug.Log("Not equal");

This prints "Equal". If we add another "1" at the end of ListA and another "5" to ListB

 List<int> A = new List<int>(new int[] { 1, 5, 6, 7, 3, 1, 1 });
 List<int> B = new List<int>(new int[] { 6, 3, 5, 1, 1, 7, 5 });

It will print "Not equal" as ListA has three times a "1"s and only one "5" while ListB has two "1"s and two "5"s

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Feb 02, 2017 at 06:08 AM 0
Share

If you have to deal with large lists it might be a good idea to initialize the lookUp "capacity" with the element count of ListA. It never needs more than that. It actually needs less if there are duplicates, but initializing the capacity large enough prevents unnecessary reallocations.

avatar image DylanST Bunny83 · Feb 02, 2017 at 06:47 AM 0
Share

Thanks, this seems to work. I was having troubles understanding it at first, but I managed to get it to work. Thank you.

avatar image
1

Answer by dpoly · Feb 01, 2017 at 04:32 AM

First, are they the same length? Second, is every element of list A to be found in list B?

You can write this easily in LINQ using .Contains().

You can make it go faster by doing a pass through list A to build an index, then a pass through list B to check against the index.

It's slightly more complex if the lists may contain duplicates.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Feb 01, 2017 at 05:38 AM 0
Share

Well, if you use a Dictionary<YourListItem, int> as index, duplicates wouldn't be a problem. You just increase the int for each element you found in A and decrease every matching element. When the counter hits 0 you can delete it from the dictionary. At the end the dictionary should be empty. If B contains an element that isn't in the dictionary you could early exit with "false".

avatar image DylanST Bunny83 · Feb 01, 2017 at 06:31 AM 0
Share

I'm having troubles figuring out how to write that.

avatar image DylanST · Feb 01, 2017 at 06:25 AM 0
Share

Thanks for replying. They would have to be the same length in order to be equal, right? The lists could contain duplicates.

This is what I have so far.

     public List<string> lst1;
     public List<string> lst2;
 
     public bool match;
 
     void Update (){
         if (lst1.Count == lst2.Count) {
             foreach (string item in lst1){
                 if (lst2.Contains (item)){
                     match = true;
                 }
             }
         } else {
             match = false;
         }
         Debug.Log (match);
     }

The only thing that doesn't work is that match = true; when there is only one correct item in each list.

avatar image dpoly · Feb 01, 2017 at 02:02 PM 0
Share

No, the code is wrong. The match variable is not initialised and the loop should ter$$anonymous$$ate early.

avatar image dpoly · Feb 02, 2017 at 08:02 AM 0
Share

@Bunny83: this will work.

You can improve the code by using foreach loops. If you do this and omit the length check this will work on IEnumerable<T>. If you do the length check the final if is not needed.

You might also benchmark it to see whether deleting keys is a hit on performance.

avatar image
1

Answer by masoudarvishian · Mar 18, 2019 at 06:48 AM

You can use the Intersect method. Here is a simple console application :

 using System;
 using System.Linq;
 
 class Program
 {
     static void Main()
     {
         var nums1 = new int[] { 2, 4, 6, 8, 10, 9 };
         var nums2 = new int[] { 1, 3, 6, 9, 12, 2 };
 
         if (nums1.Intersect(nums2).Any()) // check if there is equal items
         {
             var equalItems = nums1.Intersect(nums2); // get list of equal items (2, 6, 9)
 
             foreach (var item in equalItems)
             {
                 Console.WriteLine(item);
             }
         }
     }
 }

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dpoly · Mar 18, 2019 at 01:57 PM 0
Share

No, this is not a test for equality and in any case it won't work with lists that contain duplicates.

avatar image masoudarvishian dpoly · Mar 18, 2019 at 06:32 PM 0
Share

Are you kidding me? I have used it like a 100 times!

avatar image
1

Answer by Cazbot · Dec 09, 2019 at 07:30 AM

For anyone coming across this,

It's easier if you just sort the two lists/arrays. Then json serialize them and compare the two strings.

 using System;
 using Newtonsoft.Json;
                     
 public class Program
 {
     public static void Main()
     {
         string[] list1 = new string[] {"a", "b", "c", "d"};
         string[] list2 = new string[] {"d", "b", "c", "a"};
         
         Array.Sort(list1);
         Array.Sort(list2);
         Console.WriteLine(JsonConvert.SerializeObject(list1) == JsonConvert.SerializeObject(list2));
     }
 }

You can obviously convert that to a function pretty easily. Probably return false if they are different sizes to save on some processing. Not necessarily computationally the most efficient, but it works and it's easy to understand.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Malek-Bakeer · Feb 01, 2017 at 09:15 AM

Here you go, it has a Generic type of elements so it's portable everywhere for you

that's the code:

 using System.Collections.Generic;
 using UnityEngine;
 
 public class ListComparing : MonoBehaviour {
 
     List<string> names1 = new List<string>(new string[] {"Jordan", "Jake", "Mike", "John", "Sandra"});
     List<string> names2 = new List<string>(new string[] {"Mike", "John", "Jake", "Sandra", "Jordan"});
 
     List<int> ages1 = new List<int>(new int[] {3, 15, 7, 10});
     List<int> ages2 = new List<int>(new int[] {7, 15, 10, 3});
 
     void Start ()
     {
         //Here we give the generic value a type of string parameter to compare the lists by a string value
         print( 
             "The list of names1 and names2 equality is: " + 
             CompareLists<string> (names1, names2) 
         );
 
         //Here we give the generic value a type of int parameter to compare the lists by an int value
         print( 
             "The list of ages1 and ages2 equality is: " + 
             CompareLists<int> (ages1, ages2) 
         );
     }
 
     //A method of type bool to give you the result of equality between two lists
     bool CompareLists<T> (List<T> list1, List<T> list2)
     {
         //here we check the count of list elements if they match, it can work also if the list count doesn't meet, to do it just comment out this if statement
         if (list1.Count != list2.Count)
             return false;
 
         //here we check and find every element from the list1 in the list2
         foreach (var item in list1)
             if (list2.Find(i => i.Equals(item)) == null)
                 return false;
 
         //here we check and find every element from the list2 in the list1 to make sure they don't have repeated and mismatched elements
         foreach (var item in list2)
             if (list1.Find(i => i.Equals(item)) == null)
                 return false;
 
         //return true because we didn't find any missing element
         return true;
     }
 }
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image fafase · Feb 01, 2017 at 01:37 PM 1
Share

This is actually not going to work out if you consider duplicate (OP said there will be duplicate). If you have collection A with (1, 1, 2, 3) and collection B with (1, 2, 3, 3), your code will return true since all items from A can be found in B and vice-versa, though they are not the same.

avatar image dpoly · Feb 01, 2017 at 02:20 PM 1
Share

Why search twice? It doesn't handle duplicates either time. Try comparing a,b,b,c to a,b,c,c. You need a better method.

And did you test this properly with value types? It can fail, because the comparison to null is incorrect. Better to use FindIndex() or Contains().

  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

287 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How to check if a value exists in an array (C#) 3 Answers

Make Lists within a List 0 Answers

How do i activate a function attached to a listed GameObject from the perspective of itself? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges