4

I want to know if I can use match cases within Python to match within a string - that is, if a string contains the match case. Example:

mystring = "xmas holidays"
match mystring:
      case "holidays":
           return true
      case "workday":
           return false

I can see why it wouldn't, since this could potentially match several cases at once, but I wanted to know if it was possible.

Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46
Soop
  • 345
  • 5
  • 19
  • Can you share the error message ? Please not that this is only available in `python 3.10`. – Aymen Nov 09 '22 at 16:13
  • An approach along the lines of [the answers here](https://stackoverflow.com/q/70680363/2476977) could work, though any of those is probably overkill for this kind of issue. – Ben Grossmann Nov 09 '22 at 16:45

3 Answers3

8

You could use the [*_] wildcard sequence capture pattern: https://peps.python.org/pep-0622/#sequence-patterns

def is_holiday(yourstring: str):
    match yourstring.split():
        case [*_, "holidays"]:
            return True
        case [*_, "workday"]:
            return False


print(is_holiday("xmas holidays"))

Flynn
  • 181
  • 4
  • 1
    This is the answer IFF the user is looking for a complete substring that is separated by spaces. If however they wanted to look for "holiday" instead of holidays, this answer would not work. That said, this is an AWESOME answer showing the power of sequence wildcard capture which is definitely underutilized – Jon May 23 '23 at 14:50
4

In match statement, strings are compared using == operator which means that case patterns must be exactly equal to the match expression(mystring in this case) .

In order to solve this problem you can create a custom class which inherit from str and overrides the __eq__ method. This method should delegate to __contains__.

>>> class MyStr(str):
...     def __eq__(self, other):
...             return self.__contains__(other)
... 
>>> 
>>> mystring = MyStr("xmas holidays")
>>> match mystring:
...     case "holiday":
...             print("I am here...")
... 
I am here...
Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46
  • Raymond Hettinger (long time Python core developer) recently did [something similar](https://stackoverflow.com/a/72596437/12671057) and didn't say anything negative about it, so I'm guessing it's not a bad thing... – Kelly Bundy Nov 09 '22 at 16:47
  • @KellyBundy oh thank you for your comment. Huge fan of Raymond Hettinger here. I didn't find overriding `__eq__` to delegate to `__contains__` as a good pattern in the first place. I will edit my answer to remove those statements. – Abdul Niyas P M Nov 09 '22 at 16:55
  • I can't test with `match` right now, but I think these [two variations](https://tio.run/##fY0xDsIwEAT7e8V1tiVEQ4OQ/AQqHnBKHEexFJ3N@SjyeifI0CG23FnNlk2XzJdrkdbCOtSK9@2hYquKuwEemeKMRPFJZGtc5xNmXeIXfiJRX8KdYGJ8DwGKJFbbfWYYw2Qceo9mDMYBwO@7foUej@pMFDLrkLgS/fe1tgM) would also work. – Kelly Bundy Nov 09 '22 at 17:23
4

You can simply use the guard feature along with capture:

>>>my_str = "iwill/predict_something"
>>>match my_str:
...    case str(x) if 'predict' in x:
...        print("match!")
...    case _:
...        print("nah, dog")
...
match!
hyp3rg3om3tric
  • 449
  • 1
  • 4
  • 10