Get `if re.match(...)` result in a comprehension without assignment expression?

I’d like to use the result of re.match in the if clause of a list comprehension. The added complication is that I’m on an older Python (<3.8) where the assignment expression, a.k.a. walrus operator does not exist. I.e. I want to do something like this:

result = [ m[1] for x in ["a2", "a13", "nope", "456"] 
                      if (m:=re.match("a(\d+)", x)) ]  # result: ['2', '13'] 

But without the := operator.

I know that python internally cashes regex matches and compiled regular expressions, which leads me to believe this might be possible, but I’ll just match twice if not: [re.match(..., x)[1] for x in some_list if re.match(..., x)].

You can wrap the list on which the for is running in a function that does all the stuff that you want to do with its elements and yields the m that you need.

For example

input_list = ["a2", "a13", "nope", "456"]

def yield_numbers_from_a_strings(the_list):
  for x in the_list:
    m = re.match("a(\d+)", x)
    if m:
      yield m

result = [m[1] for m in yield_numbers_from_a_strings(input_list)]
1 Like

The re module caches compiled regular expressions, but not matches.

Assignment in a comprehension:

result = [m[1] for x in ["a2", "a13", "nope", "456"] for m in [re.match(r"a(\d+)", x)] if m]

It’s clunky and absolutely deserves an explanatory comment (including noting down that this needs to support Pythons before 3.8), but it will work.

1 Like