Avoid duplicated operations in lambda functions

I'm using a lambda function to extract the number in a string:

text = "some text with a number: 31"
get_number = lambda info,pattern: re.search('{}\s*(\d)'.format(pattern),info.lower()).group(1) if re.search('{}\s*(\d)'.format(pattern),info.lower()) else None
get_number(text,'number:')

How can I avoid to make this operation twice?:

re.search('{}\s*(\d)'.format(pattern),info.lower()

Upvotes: 0

Views: 54

Answers (2)

ospahiu
ospahiu

Reputation: 3525

You can use findall() instead, it handles a no match gracefully. or is the only statement needed to satisfy the return conditions. The None is evaluated last, thus returned if an empty list is found (implicit truthiness of literals like lists).

>>> get_number = lambda info,pattern: re.findall('{}\s*(\d)'.format(pattern),info.lower()) or None
>>> print get_number(text, 'number:')
['3']
>>> print get_number(text, 'Hello World!')
>>>

That being said, I'd recommend defining a regular named function using def instead. You can extract more complex parts of this code to variables, leading to an easier to follow algorithm. Writing long anonymous function can lead to code smells. Something similar to below:

def get_number(source_text, pattern):
    regex = '{}\s*(\d)'.format(pattern)
    matches = re.findall(regex, source_text.lower())
    return matches or None

Upvotes: 3

mitoRibo
mitoRibo

Reputation: 4548

This is super ugly, not going to lie, but it does work and avoids returning a match object if it's found, but does return None when it's not:

lambda info,pattern: max(re.findall('{}\s*(\d)'.format(pattern),info.lower()),[None],key=lambda x: x != [])[0]

Upvotes: 1

Related Questions