Wiz
Wiz

Reputation: 4865

Python - testing if an object attribute is equal to a given value

Say you have a list of people.

class Person:
    def __init___(self, name, id):
        self.name = name
        self.id = id

people = []
for x in xrange(0,100)
    #find people and append to people list

Now, I have a list of people objects. How could I most efficiently find, say, a person whose name is "Bob" from the people list?

Upvotes: 0

Views: 1368

Answers (3)

mjgpy3
mjgpy3

Reputation: 8937

One way you could do it is by building a class to hold collections of people objects. One of the best ways to do this may be something like the following code:

class People:
    def __init__(self):
        self.members = {}

    def add_person(self, person):
        self.members[person.name] = person

    def __getitem__(self, name):
        return self.members[name]

class Person:
    def __init__(self, name, id):
        self.name = name
        self.id = id

Now you should be able to fill up the People object like such:

# Add people to a People object
people = People()
people.add_person(Person('Bob', 1))
people.add_person(Person('Surly', 2))

# Get a person by their name
people['Bob']    # Returns instance that is People('Bob', 1)

Also just to let you know, I think your Person class' __init__ method has too many underscores in it. Hope this helps.

Upvotes: 0

Claudiu
Claudiu

Reputation: 229321

For this exact scenario, you'll want to use a dictionary:

from collections import defaultdict
people = [...]
name_to_people = defaultdict(list)
for p in people:
    name_to_people[p.name].append(p)

Then whenever you want to find all people whose name is "Bob":

bobs = name_to_people["Bob"]

It will return empty list for no match, a list with one element if there's exactly one person with that name, or a list with multiple elements if there are multiple Bobs.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121406

With just a list and no other indices, you have to use a list comprehension:

matching = [p for p in people if p.name == 'Bob']

but if you have to do that a lot, you may want to create an index:

from collections import defaultdict

nameindex = defaultdict(list)
for person in people:
    nameindex[person.name.lower()] = person

nameindex['bob']  # a list of people named Bob.

This way you only have to loop through all your people once (cost O(N)), after which any name lookup has constant cost (O(1)).

Upvotes: 4

Related Questions