Search Unity

How to test two ArrayList (C#) instances for value equality?

Discussion in 'Scripting' started by twilightZone, Jan 25, 2016.

  1. twilightZone

    twilightZone

    Joined:
    Oct 10, 2014
    Posts:
    30
    Hello all,

    My question is simple, but I want to test if 2 arrayLists (prout and prout2) contains the same items.
    this portion of code --> prout[item] == prout2[item] does not works
    but this one --> prout[item].Equals(prout2[item]) works

    Is it the good and easy solution ??

    Thanks a lot
    Patrick
    Code (CSharp):
    1. ArrayList prout = new ArrayList(new ArrayList{10, 20, 30});
    2. ArrayList prout2 = new ArrayList(new ArrayList{10, 20, 30});
    3.  
    4. for (int item = 0; item < prout.Count; item++) {
    5.     if (prout[item] == prout2[item]) {
    6.         Debug.Log("== method " + item + "  " + prout[item] + "   " + prout2[item]);
    7.     }
    8. }
    9.    
    10. for (int item = 0; item < prout.Count; item++) {
    11.     if (prout[item].Equals(prout2[item])) {
    12.         Debug.Log("Equals method " + item + "  " + prout[item] + "   " + prout2[item]);
    13.     }
    14. }
    15.  
    16. /// Returns
    17. /// Equals method 0  10   10
    18. /// Equals method 1  20   20
    19. /// Equals method 2  30   30
    20.  
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Sort them, if the two values are not the same at the exact same point, then they are not equal.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5.  
    6. public class Test2 : MonoBehaviour
    7. {
    8.     bool ArrayListEquals(ArrayList prout1, ArrayList prout2)
    9.     {
    10.         // if the two counts are not the same, they obviously are not equal.
    11.         if (prout1.Count != prout2.Count) return false;
    12.  
    13.         // sort them.
    14.         prout1.Sort();
    15.         prout2.Sort();
    16.  
    17.         // after sorting, if the two numbers at the same place
    18.         // are not the same then the two are not equal
    19.         for (var i = 0; i < prout1.Count; i++) {
    20.             if (!prout1[i].Equals(prout2[i])) return false;
    21.         }
    22.  
    23.         return true;
    24.     }
    25. }
    26.  
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    I believe this is a difference between comparing references (==) and comparing values (.Equals). However, when using arrays, I would expect == to compare values when dealing with a value type like int. However, you're not using arrays, exactly; you're using ArrayList. I've never used it, but apparently ArrayList behaves poorly in a scenario like this.

    Short answer: Use List<int> instead.
    Code (csharp):
    1. //top of script
    2. using System.Collections.Generic;
    3. //in functions
    4. List<int> prout = new List<int>(new int[]{10, 20, 30} );
    5. if (prout[2] == whatever) {
    Long answer: ArrayList is not a generic class - in other words, it has no idea what classes are in it. You can put in string, ints, GameObjects, whatever. With that in mind, when you call ==, it has no choice but to compare references - to compare memory addresses. prout[item] is not an int, it's an object. When you created these, you gave them two different copies of the number 10.

    With a List<int>, however, the class knows what it's holding. with a List<int>, prout[item] is properly an int, and so when the compiler sees ==, it knows that you want to compare values.
     
  4. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    974
    I feel like ArrayList should be marked deprecated. I'm not aware of any reason you should use it over the strongly typed, generic List<T>.

    I was thinking about the behavior seen here and it occurred to me that comparing an object in the ArrayList to itself would probably fail as well. Something like
    Code (CSharp):
    1. ArrayList prout = new ArrayList(new ArrayList{10, 10});
    2.  
    3. if (prout[0] == prout[0])
    4.   Debug.Log("10 is equal to itself");
    Unintuitive, to me at least, this actually works. I was able to reason out why but..

    of course, this does not work.
    Code (CSharp):
    1. ArrayList prout = new ArrayList(new ArrayList{10, 10});
    2.  
    3. if (prout[0] == prout[1])
    4.   Debug.Log("10 is equal to itself");
    A very tricky gotcha.. I would definitely stick with List<int> as StarManta suggested.
    bigmisterb also has a good point you shouldn't overlook. If the lists can be changed at runtime, you'll need to sort them using the same algorithm before doing a side by side comparison.

    In case you're interested, .Equals() works because is it virtual and the correctly overridden flavor can be looked up at runtime to determine that int.Equals(int) should be used instead of object.Equals(object). The == operator is static, so its implementation needs to be decided at compile time, so it is stuck doing the object == object comparison.
     
    Last edited: Jan 25, 2016
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    One other addition, for completeness: before you even loop through anything, check to see if the lists are the same length. If they're not, you can return false immediately (and looping through them would either cause an error or a false positive).
     
  6. twilightZone

    twilightZone

    Joined:
    Oct 10, 2014
    Posts:
    30
    Perhaps, I made the wrong choice.
    I must have an array, that must be dynamic and I need to store in it string, integer, float and array of array.
    For example, I need to store
    [10, 3.14, "pat", [20, 10, "joe"], 22]

    ArrayList seems to be my unique solution.

    Your advice is welcome :)