Rayne
Rayne

Reputation: 14977

Compare 2 class elements in Python

I have a class defined below:

class Members(object):
   def __init__(self, first_name, last_name, age):
      self.first_name = first_name
      self.last_name = last_name
      self.age = age

I then created 2 lists containing instances of the class:

CourseA = []
CourseB = []

// Extract (multiple) first_name, last_name, age from a file
CourseA.append(Members(first_name, last_name, age)) # called multiple times

// Extract (multiple) first_name, last_name, age from a file
CourseB.append(Members(first_name, last_name, age)) # called multiple times

So basically I have 2 lists like the following:

# CourseA
John, Smith, 12
Jane, Doe, 14
Susan, Patton, 13

# CourseB
Richard, Lane, 12
Susan, Patton, 13

Now I want to compare the first_name and last_name of CourseA and CourseB. If both are the same, then print the corresponding age. In this case, "Susan Patton" is the common name in both lists, so I would print "13".

What is the most efficient way to do this? Both lists are huge, and I thought of comparing one name from CourseA to all names in CourseB, then compare the next name in CourseA to all names in CourseB, but this seems like a very slow method.

ETA: So now I have included the following in the class definition.

def __hash__(self):
   return hash((self.first_name, self.last_name))

def __eq__(self):
   try:
        return (self.first_name, self.last_name) == (other.first_name, other.last_name)
   except AttributeError:
        return False

Then, I have the following to do the comparison. BTW, it seems like the comparison below works even without the __eq__ and __hash__ in my class definitions.

CourseA_set = set((x.first_name, x.last_name) for x in CourseA)
CourseB_set = set((y.first_name, y.last_name) for y in CourseB)

for (caller, callee) in CourseA_set.intersection(CourseB_set):
   print ("Found: {0}".format((caller, callee)))

I do get the first_name and last_name that is found in both CourseA and CourseB. However, how do I get the other corresponding attributes from CourseA and CourseB, like age?

Do I have to search through the CourseA and CourseB lists for matching (first_name, last_name) to get the corresponding age? This seems to be inefficient.

Upvotes: 0

Views: 149

Answers (1)

Moses Koledoye
Moses Koledoye

Reputation: 78556

You're replacing the class instances with tuples containing their attributes. You should instead keep the instances as they are in the lists, then turn the lists into sets without stripping the attributes off the class

CourseA_set = set(CourseA) # no set comprehension
CourseB_set = set(CourseB)

for member in CourseA_set.intersection(CourseB_set):
     print ("Found: {f} {l} {a}".format(f=member.first_name, 
                                        l=member.last_name, 
                                        a=member.age))

The __hash__ and __eq__ methods you already implemented will ensure only the instances with matching first_name and last_name from both sets are kept after doing the intersection.

Upvotes: 1

Related Questions