Ivan Borshchov
Ivan Borshchov

Reputation: 3555

Assign and compare in python

I need to do re.match sequentially, and in match case I need result of match to optain groups. Now I can do next:

r = re.match('cond1', l)
if r:
    # work with r.group()
else:
    r = re.match('cond2', l)
    if r:
        # work with r.group()
    else:
        r = re.match('cond3', l)
        if r:
            # work with r.group()

etc. But how can I do better? I see it is not possible to perform assignment in if like this:

if r = re.match('cond1', l):
    # work with r.group()
elif r = re.match('cond2', l):
    # work with r.group()
elif r = re.match('cond3', l)
    # work with r.group()

Upvotes: 0

Views: 60

Answers (2)

khelwood
khelwood

Reputation: 59112

You could use a comprehension:

r, cond = next((m,c) for (m,c) in ((re.match(cond, line), cond) for cond in ('cond1', 'cond2', 'cond3')) if m)

if cond=='cond1':
    # work with r.group() for cond1
elif cond=='cond2':
    # work with r.group() for cond2

Or if that looks too arcane, a loop:

for cond in ('cond1', 'cond2', 'cond3'):
    r = re.match(cond, line)
    if r:
        break

if not r:
    # no match
elif cond=='cond1':
    # work with r.group() for cond1
elif cond=='cond2':
    # work with r.group() for cond2

Upvotes: 3

abarnert
abarnert

Reputation: 365767

First, it often helps to refactor things out into functions. In this case, it helps because you can easily return early from a function; you can't return early from a block of code in the middle of other code.

def first_match(haystack):
    r = re.match('cond1', haystack)
    if r:
        # work with r.group()
        return
    r = re.match('cond2', l)
    if r:
        # work with r.group()
        return
    r = re.match('cond3', l)
    if r:
        # work with r.group()

All the else bits and indentation headaches go away.


Also, in general, when you're asking how to chain 3 or more things together, the right answer is to figure out how to chain any arbitrary number of things together, and just do that with N=3. Which usually means a loop (or a loop hidden inside a function like map, or a recursive function definition, etc.). For example:

def first_match(exprs, haystack):
    for expr in exprs:
        r = re.match(expr, haystack)
        if r:
            return r

In this case, however, what you're trying to do is actually doable. Maybe not a good idea, but… A regex match object is always truthy. And of course None is falsey. So:

r = re.match('cond1', l) or re.match('cond2', l) or re.match('cond3', l)
if r:
    # work with r.group(), which is the group for whichever matched

But notice that if you want to use the truthiness, you can do that in a loop too:

next(filter(bool, (re.match(cond, l) for cond in ('cond1', 'cond2', 'cond3'))))

Finally, you're already using regular expressions, so why not use regular expressions?

r = re.match('cond[123]', l)
if r:
    # work with r.group()

Upvotes: 1

Related Questions