Need some help with comparing lists and or sets in Python

I have been banging my head against the wall a bit on this one…

The Problem
So I have bunch of Cameras that I import into maya I then compare their transforms to see if their world space transforms are a match. I then create lists of all the matches with in a Master list The output for the code looking for the matches is something like this…

A list containing lists… for example

MasterItemContainer = []

Code Runs which imports the Cameras runs comparisons between all the Cameras and loads up
MasterItemContainer now contains Lists of matches so…

for items in MasterItemContainer:
print items
output looks like this

MasterItemContainer[0] Looks like [camera_010,Camera_040,Camera,90]
MasterItemContainer[1] Looks like [camera_020,camera_080,camera_110]
etc…

So I suppose I am creating a mutli dimensional array or a list containing lists to store all the matches.
The issue I am having is that because I have to compare all the cameras to each other and store the out comes I get duplicate data for instance say I have 40 cameras to check and camera 010 and camera 080 share the same info now I have two lists with duplicate data

MasterItemContainer[0][Camera_010, Camera_030,Camera_010]

MasterItemContainer[6][Camera_080, Camera_030, Camera_010]

Bad out come if your running a check on 80 or so cameras… I feel like the real issue is the logic that I am using to load up the lists… I have to check each camera against the other cameras but once I run a check on one camera it should get removed the next time I run through the loop, but I am not sure how to do it. Any thoughts would be great :slight_smile:

Well, I bet there are better ways, but here is a way you could just sort them out by using their transform and attributes as a dictionary key. Instead of comparing them to each other, just collect some info, and sort that way.

I am using PyMEL. And I create a function that returns a tuple of information about the camera, including transform and focalLength, etc. Use the info that makes sense to you. A tuple is hashable, so it can be used a dictionary key. (A list cannot.)

Then that tuple of info is the dictionary key. And you can sort out each camera into those keys.

import pymel.core as pm

def camera_data(cam):
    # Test not only the transform, but focalLength and anything else that would distinguish a camera.
    attrs = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz']
    shapeAttrs = ['focalLength', 'shutterAngle']
    allAttrs = [cam.getTransform().attr(eachAttr).get() for eachAttr in attrs]
    allAttrs.extend(cam.attr(eachAttr).get() for eachAttr in shapeAttrs)
    return tuple(allAttrs)

myCameras = {}
for cam in pm.ls(type='camera'):
    cameraTransform = cam.getTransform()
    newKey = camera_data(cam)
    if myCameras.has_key(newKey):
        # if the key exists, append
        myCameras[newKey].append(cameraTransform)
    else:
        # otherwise, start a new list
        myCameras[newKey] = [cameraTransform]

for k, v in myCameras.items():
    print(k)
    print(v)

Hi @PWJ, welcome back! :slight_smile: ,

You can use reverse in your list comprehension - its very powerful as it allows you to pop item thus reducing the list whilst being able to iterate over it. Roughly speaking…

names = ["a", "b", "c", "d", "e", "f", "g"]  # your cameras
values = [1, 2, 1, 4, 10, 4, 2] #  their values

data = zip(names, values) # zipped camera to respective values

data.reverse()  # reverse the data as we'll work backwards
matched = []  # the matching data
skips = []  # during the second loop *j* we check if we have matching items and append them here

for i in reversed(range(len(data))):  # iterate backwards so we can pop the values

  found = [] # empty list of found matching

  if data[i][0] not in skips:  # only set found if it's not in skips.
    found = [data[i][0]]

  for j in reversed(range(len(data))):

    if i != j:  # skip the current index matching itself

      if data[i][1] == data[j][1]: # its a match!, or not...

        if data[j][0] not in skips:  # only do the work if it's not in skips

          found.append(data[j][0]) # append the found
          skips.append(data[j][0])  # append the skips i.e. if a == b, c, d, add b, c, d to skips

  if found:
    matched.append(found)  # only append matched if found

  data.pop(i)  # the *magic* pop - pull the current item

print matched

# >> [['a', 'c'], ['b', 'g'], ['d', 'f'], ['e']]

“A tuple is hashable, so it can be used a dictionary key. (A list cannot.)”
Thanks for tip good to know!

I am not familiar with Dictionary but this seems to be a better way than Building and comparing lists. Thanks clesage :smiley: