check existence of element in list

Viewed 86

I have a list of Person objects and I'd like to check if a person exists based on their name. Is there an easier way to do so other than this loop?

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


found = False

for p in person_list:
    if p.name == "Alan":
        found = True
        break
3 Answers
any(p.name == "Alan" for p in person_list)

It returns you a bool literal - True or False

You could try with any:

found = any(p.name == 'Alan' for p in person_list)

And printing found would give either True or False.

Or you could also do a list comprehension:

found = not not [p for p in person_list if p.name == 'Alan']

You can first make a list of names and then use the count method:

list(map(lambda x: x.name, person_list)).count('Alan') > 0

It will return False if the person doesn't exist in the list.

I performed a speed test comparing map and any approach:

names = list(map(str, np.random.randint(0, 10, 1000)))

person_list = [Person(name) for name in names]

%timeit list(map(lambda x: x.name, person_list)).count('Alan') > 0

%timeit any(p.name == 'Alan' for p in person_list)

and the results:

207 µs ± 34.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
122 µs ± 17.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

So any approach is faster.

UPDATE

Using attrgetter with map reaches the best performance:

from operator import attrgetter
f = attrgetter('name')

names = list(map(str, np.random.randint(0, 10, 1000)))

person_list = [Person(name) for name in names]

%timeit list(map(f, person_list)).count('Alan') > 0

%timeit any(f(p) == 'Alan' for p in person_list)

And the result:

110 µs ± 18.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
172 µs ± 6.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Related