How to use multiple cases in structural pattern matching (switch case) in Python 3.10

1.3k Views Asked by At

Like in this question, I am trying to match an element in a list, and handle the cases accordingly. See the example below.

direct_payments = ["creditcard", "debitcard"]
on_credits = ["gift card", "rewards program"]

def print_payment_type(payment_type):
    match payment_type:
        case in direct_payments:
            print("You paid directly!")
        case in on_credits:
             print("You paid on credits!")

print_payment_type("gift card")

I want this to print "You paid on credits". I am convinced that using structural pattern matching is the most readable option in my case. Is there any way to achieve this behaviour? I cannot use "gift card" | "rewards program", because I need to use the lists elsewhere.

4

There are 4 best solutions below

2
kgkmeekg On
  • case needs to a pattern (the feature is called structural pattern matching after all). So we cannot include a function there (e.g. case XX in direct_credits.) [Thanks to matszwecja for this clarification.]

  • The cases are generated by the match statement. So we cannot do this case in direct_payments:.

I could think of an application of case like this:

direct_payments = ["creditcard", "debitcard"]
on_credits = ["gift card", "rewards program"]

def find_val(value, arrays):
    for i, arr in enumerate(arrays):
        if value in arr:
            return i
    return -1

def print_payment_type(payment_type):
    match find_val(payment_type, [direct_payments, on_credits]):
        case 0:
            print("You paid directly!")
        case 1:
            print("You paid on credits!")

print_payment_type("gift card")

However, I do not understand why you would prefer case over if/ elif/else. You could combine your requirements easily using and/or. Anything that you want to do using match-case should be easily doable using elif` conditions.

direct_payments = ["creditcard", "debitcard"]
on_credits = ["gift card", "rewards program"]

def print_payment_type(payment_type):
    if (payment_type in direct_payments) and (payment_type not in on_credits):
        print("You paid directly!")
    elif payment_type in on_credits:
        print("You paid on credits!")

print_payment_type("gift card")

This link should be where you can get more examples of using case.

EDIT: gimix has a better answer.

0
Anton Yang-Wälder On

You could use structural pattern matching like this:

def print_payment_type(payment_type):
    match payment_type:
        case "creditcard" | "debitcard":
            print("You paid directly!")
        case "gift card" | "rewards program":
            print("You paid on credits!")


print_payment_type("gift card")

However, this might not be the most elegant option because you "lose" the direct_payments and on_credits lists.

0
gimix On

This works:

def print_payment_type(payment_type):
    match payment_type:
        case payment_type if payment_type in direct_payments:
            print("You paid directly!")
        case payment_type if payment_type in on_credits:
             print("You paid on credits!")
0
AziMez On

You can use a dictionary, like this:

my_dict = {'direct_payments': ["creditcard", "debitcard"],
    'on_credits': ["gift card", "rewards program"]}


def print_payment_type(payment_type):
    selected_key=next(key for key, value in my_dict.items() if payment_type in value)
    print("The selected dictionary key is", selected_key)
    match selected_key:
        case "direct_payments":
            print("You paid directly!")
        case "on_credits":
             print("You paid on credits!")

print_payment_type("gift card")