0

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

m3trik
  • 333
  • 2
  • 13

2 Answers2

3

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

theodox
  • 12,028
  • 3
  • 23
  • 36
  • Nice idea with `hash`! There's an unexpected result doing `hash(-1) == hash(-2)` posted here, but there wasn't a clear explanation: https://stackoverflow.com/questions/17585730/what-does-hash-do-in-python +1 – Green Cell May 22 '18 at 08:09
  • Python's default hash for -1 is -2, which is a known irritant that's now canonical and will never change.... however it's only for exactly -1, so for this application it's unlikely to be a problem – theodox May 22 '18 at 16:52
1
>>> l1 = [[[1,2], 10.], [[3, 4], 5.0]]
>>> l2 = [[[1,2], 8.], [[3, 6], 5.0]]

>>> [(v1[0] == v2[0] and v1[1] == v2[1]) for (v1,_), (v2,_) in zip(l1, l2)]
[True, False]

Replace integer values in l1, l2 with "Points" in the above example. Obviously, this assumes that dt.Point objects can be compared directly.

AGN Gazer
  • 8,025
  • 2
  • 27
  • 45
  • In my particular case, the hash method was a better fit. I will definitely keep the use of generator expressions in mind for future projects though. -thanks – m3trik May 22 '18 at 17:28