pythonpython-3.xlistcompare

How to compare two list of objects using the object's equal method in Python


I have a class that comes with a .equals() method. I'd like to compare two unordered lists of these objects to see if they are not equal.

My current approach is to loop through list 1, then loop through list 2.

def objectListsNotEqual(list_1, list_2):
    if(len(list_1) != len(list_2)):
        return True

    # same length lists, so check it
    for obj_1 in list_1:
        if(not(any(obj_1.equals(obj_2) for obj_2 in list_2))):
            return True

    for obj_2 in list_2:
        if(not(any(obj_2.equals(obj_1) for obj_1 in list_1))):
            return True

    # if execution reaches here, then both lists match
    return False

However, this doesn't account for when list 1 and list 2 have different counts when the .equals() method returns True. e.g. if I had:

list_1 = [obj_1(foo), obj_2(foo), obj_3(bar)]
list_2 = [obj_4(foo), obj_5(bar), obj_6(bar)]

objectListsNotEqual(list_1, list_2) # --> returns False due to the use of any() function

I would want the function to return False in the above example since they have different counts of foo and bar instances of the object.

Edit: class is a Polyline which is built from the Geometry object. Don't really know how it works internally.


Solution

  • Assuming it's equality of the geometry you're interested in then you could utilise the Geometry class's JSON property.

    Let's emulate the Geometry class by giving it a JSON property (which is a string) then we can do this:

    from random import randint
    from json import dumps
    
    # if we had full control over this class we would obviously implement
    # two crucial dunder methods - i.e., __lt__ to enable sorting and __eq__ for testing equality
    # so let's just emulate the ArcGIS class
    class Geometry:
        def __init__(self):
            self._JSON = dumps({"x": randint(1, 360), "y": randint(1, 360)})
    
        @property
        def JSON(self):
            return self._JSON
    
    def are_lists_equal(lista, listb):
        return set(g.JSON for g in lista) == set(g.JSON for g in listb)
    
    lista = [Geometry() for _ in range(10)]
    listb = [Geometry() for _ in range(10)]
    
    print(are_lists_equal(lista, listb))