Ishan Bhatt
Ishan Bhatt

Reputation: 10231

How to check for an attribute from the list of objects in python

I have a list called stops. And it has stop objects with attributes (fields) stop_id, stop_name and stop_type. I need to check if all stop_id have the correct prefix or not.

I came up with following, but I am sure there has to be better way of traversing and matching:

stop_ids = [stop.stop_id for stop in stops]
for stop_id in stop_ids:
    if prefix in stop_id:
        pass

Upvotes: 0

Views: 78

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121406

You can use a generator expression with all():

if not all(stop.stop_id.startswith(prefix) for stop in stops):
    # at least one `stop_id` does *not* start with the prefix

You can also express this with the any() function:

if any(not stop.stop_id.startswith(prefix) for stop in stops):
    # at least one `stop_id` does *not* start with the prefix

If you want the if suite to be executed when all stop_id values do have the prefix, then use all() without the not:

if all(stop.stop_id.startswith(prefix) for stop in stops):
    # *all* `stop_id` values start with the prefix

Both any() and all() short-circuit; they stop iterating over the generator expression as soon as the first evidence is found that determines the outcome; for all() as soon as one False is found iteration ends and False is returned, for any() iteration stops with the first True.

Note that I used str.startswith() rather than in to test if the id starts with the given prefix; the in membership test would allow the prefix to appear anywhere in the string, not just the start.

If you need to list values that don't match, use a list comprehension:

not_prefixed = [stop for stop in stops if not stop.stop_id.startswith(prefix)]
if not_prefixed:
    # you have `stop_id` values that are not properly prefixed

I collected stop objects here, but you can also collect the stop_id values if that is more convenient:

not_prefixed = [stop.stop_id for stop in stops if not stop.stop_id.startswith(prefix)]

but if you only need to get the first, then again generator expressions are the answer here, combined with the next() function:

not_prefixed = next((stop.stop_id for stop in stops if not stop.stop_id.startswith(prefix)), None)
if not_prefixed is not None:
    # you have at least one stop_id that wasn't prefixed, the first 
    # such is stored in not_prefixed.

Upvotes: 3

LittleQ
LittleQ

Reputation: 1925

stops whose stop_id is invalid

invalid_stops = filter(lambda x: not x.stop_id.startswith(prefix), stops)

Upvotes: 0

Related Questions