Search code examples
pythonpython-2.7maya

Comparing lists within two lists for a match in python


I have two lists. Each list contains a list containing a list of two point values, and a float value that is associated with those points.

ex. list one [index 0]:
[[dt.Point([43.61, 24.88, -37.41]), dt.Point([42.33, 21.59, -31.28])], 10.0] etc.

list two: same format.

I am trying to compare the point values between the two lists for an exact match
(meaning list1[0][0] == list2[0][0])

-thanks for any help


Solution

  • For this kind of thing you might want to make a simple class with a custom hash method so you can spot identical values. That way you don't have to get into the messy business of comparing all the values against each other. Once you can hash the unique combination of two points and a value, you just make two sets of your lists and intersect them.

    A basic example would look something like this (with openMaya MVectors instead of pymel points -- but the idea's the same)

    from maya.api.OpenMaya import MVector
    
    class PointHash(object):
    
        def __init__(self, p1, p2, v):
            self.p1 = p1
            self.p2 = p2
            self.value = v
            self._hashvalue = hash((p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, v))
    
        def __hash__(self):
            return self._hashvalue
    
        def __eq__(self, other):
            return hash(self) == hash(other)
    
        def __repr__(self):
            return "PointHash %i" % self.__hash__()
    
    
    #sample data
    a = MVector(1.1, 2.2, 3.3)
    b = MVector(1.0009, 2.00019, 3.0001)
    c = MVector(21.0, 22.0, 23.0)
    
    
    # some lists
    set_one = set((PointHash(a, b, 1.0), PointHash(b, a, 1.0), PointHash(a, b, 2.0), PointHash(b, c, 1.0)))
    set_two = set((PointHash(a, b, 1.0), PointHash(b, a, 1.1), PointHash(a, b, -1.0), PointHash(b, c, 1.0)))
    
    print "common:"
    for item in set_one.intersection(set_two):
        print item.p1, item.p2, item.value
    
    
    #> (1.1, 2.2, 3.3) (1.0009, 2.00019, 3.0001) 1.0
    #> (1.0009, 2.00019, 3.0001) (21, 22, 23) 1.0
    

    As written this will require an EXACT match to produce the same values, you may find that you want to quantize the actual vertex values or whatever to some coarser resolution to catch near-misses too. As written it also assumes that PointHash(a,b, 1.0) is not the same as PointHash(b,a,1.0) which may or may not be the desired behavior.

    The actual hashing is done in the __init__ method and it steals python's built-in tuple hashing which is nice and fast.

    Related: http://discourse.techart.online/t/geometry-hash/3144