HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMajor

Search for a multiword string in a list of strings

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
searchmultiwordforliststringsstring

Problem

Unlike Perl, you can't to my knowledge match a regular expression inside an if statement in Python and assign the result to a variable at the same moment. This leads to typical constructs like this:
match = re.search(REGEX, STRING)
if match:
# do something


So far, so Python. But what if I want to iterate through a file / array of lines, check each line for a few regexes, and fire a catch-all when none has matched? I can't think my way around a rather unwieldy and deeply nested if-else-if-else...-construction:
import re
strings = ["abc zzz", "y", "#comment"]
for s in strings:
match = re.search("(\S+) (\S+)", s)
if match:
print "Multiword: %s+%s" % (match.group(1), match.group(2))
else:
match = re.match("y$", s)
if match:
print "Positive"
else:
match = re.match("n$", s)
if match:
print "Negative"
else:
# a few more matches possible in real life script,
# and then the last catch-all:
print "No match found, line skipped"


Isn't there any way to put this in a much nicer looking elif-construction or something? The following doesn't work in Python, because if-clauses take only expressions, not statements. However, something along these lines would strike me as pythonic, or am I blind to something obvious here?
if match = re.search(" ", s):
print "Multiword: %s+%s" % (match.group(1), match.group(2))
elif match = re.match("y$", s):
print "Positive"
else:
print "No match found, line skipped"

Solution

You can use the continue keyword to force advancement and move on to evaluating the next string.
Code after each if statement will only execute if the test in the previous statement was false.

import re
strings = ["abc zzz", "y", "#comment"]
for s in strings:
    match = re.search("(\S+) (\S+)", s)
    if match:
        print "Multiword: %s+%s" % (match.group(1), match.group(2))
        continue
    match = re.match("y$", s)
    if match:
        print "Positive"
        continue
    match = re.match("n$", s)
    if match:
        print "Negative"
        continue
    
    # a few more matches possible in real life script,
    # and then the last catch-all:
    print "No match found, line skipped"


Revisiting in 2021

Since Python 3.8 we now have assignment expressions! You can do something like this:

import re
strings = ["abc zzz", "y", "#comment"]
for s in strings:
    if match := re.search("(\S+) (\S+)", s):
        print("Multiword: %s+%s" % (match.group(1), match.group(2)))

    elif match := re.match("y$", s):
        print("Positive")

    elif match := re.match("n$", s):
        print("Negative")

    # a few more matches possible in real life script,
    # and then the last catch-all:
    else:
        print("No match found, line skipped")

Code Snippets

import re
strings = ["abc zzz", "y", "#comment"]
for s in strings:
    match = re.search("(\S+) (\S+)", s)
    if match:
        print "Multiword: %s+%s" % (match.group(1), match.group(2))
        continue
    match = re.match("y$", s)
    if match:
        print "Positive"
        continue
    match = re.match("n$", s)
    if match:
        print "Negative"
        continue
    
    # a few more matches possible in real life script,
    # and then the last catch-all:
    print "No match found, line skipped"
import re
strings = ["abc zzz", "y", "#comment"]
for s in strings:
    if match := re.search("(\S+) (\S+)", s):
        print("Multiword: %s+%s" % (match.group(1), match.group(2)))

    elif match := re.match("y$", s):
        print("Positive")

    elif match := re.match("n$", s):
        print("Negative")

    # a few more matches possible in real life script,
    # and then the last catch-all:
    else:
        print("No match found, line skipped")

Context

StackExchange Code Review Q#45220, answer score: 32

Revisions (0)

No revisions yet.