Reputation: 10231
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
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
Reputation: 1925
stops
whose stop_id is invalid
invalid_stops = filter(lambda x: not x.stop_id.startswith(prefix), stops)
Upvotes: 0