Reputation: 4069
How can I use structural pattern matching for the following use case:
values = ["done 0.0", "done 3.9", "failed system busy"]
for v in values:
vms = v.split()
match vms:
case ['done', float()>0]: # Syntax error
print("Well done")
case ['done', float()==0]: # Syntax error
print("It is okay")
case ['failed', *rest]:
print(v)
Please excuse me for the syntax errors, I have written this to demonstrate my thought process.
What could be the right syntax to achieve this pattern matching? Is it even possible?
Upvotes: 1
Views: 132
Reputation: 5379
Almost got it. You missed referencing the second value.
values = ['done 0.0', 'done 3.9', 'failed system busy']
for v in values:
match v.split():
case 'done', x if float(x) > 0:
print('Well done')
case 'done', x if float(x) == 0:
print('It is okay')
case 'failed', *rest:
print(v)
Also, you may want to add a last case that catches the not covered ones:
case _:
print('Any other case')
This is clearer and more concise than the ìf-then-else-try-catch
alternative. Actually, match
was created just for cases like this one. That's why it's called structural pattern matching.
Upvotes: 1
Reputation: 5450
if ...else
would be simpler but if you do want pattern matching then you have a number of issues to be resolved. Your string does not contain a float, it contains a string of characters which could be converted to a float. So to test value of a float you have to test that it IS a float in string form and then convert to a float then test. The 'wildcard' character is _
which should be used to capture non-matching elements with *_ to catch any number of other elements. The following code does what I think you want and could be the basis for further development. Firstly Regex is used to test for the float with a 'guard' expression in the pattern. The Regex would pick up error entries such as "3.x".
import re
values = ["done 0.0", "done 3.9", "failed system busy"]
for v in values:
vms = v.split()
match vms:
case ['done', x] if x == '0.0': print(vms, 'It is OK')
case ['done', x] if re.match(r'\d+.\d+', x) and float(x) > 3.0: print(vms, 'Well done')
case ['failed', *_]: print(v)
case _: print('unknown case')
produces:
['done', '0.0'] It is OK
['done', '3.9'] Well done
failed system busy
Another way, without Regex, would be to write a checking function such as:
def check_float(f):
f = f.strip()
try:
_ = float(f)
except:
return False
return True
and then the case would be:
case ['done', x] if check_float(x) and float(x) > 3.0: print(vms, 'Well done')
Upvotes: 1