Найти тему
Удалёнка

Python. Массивы в pattern matching

Оглавление

В качестве шаблонов также могут выступать массивы. Подобным шаблоны также могут содержать либо конкретные значения, либо переменные, которые передаются элементы массивов, либо символ прочерка _, если элемент массива не важен:

def print_people(people):

match people:

case ["Tom", "Sam", "Bob"]:

print("default people")

case ["Tom", second, _]:

print(f"Second Person: {second}")

case [first, second, third]:

print(f"{first}, {second}, {third}")

print_people(["Tom", "Sam", "Bob"])         # default people

print_people(["Tom", "Mike", "Bob"])        # Second Person: Mike

print_people(["Alice", "Bill", "Kate"])     # Alice, Bill, Kate

print_people(["Tom", "Kate"])               # несоответствует ни одному из шаблонов

В данном случае функция print_people принимает массив, который, как предполагается, состоит из трех элементов.

Первый шаблон предполагает, что элементы массива имеют определенные значения:

case ["Tom", "Sam", "Bob"]:

print("default people")

В данном случае первый элемент массива должен представлять строку "Tom", второй - строку "Sam" и третий - строку "Bob".

Второй шаблон предполагает, что первый элемент массива должен быть равне строке "Tom", остальные два элемента могут иметь произвольные значения:

case ["Tom", second, _]:

print(f"Second Person: {second}")

При этом значение второго элемента передается в переменную second, а значение третьего элемента не важно, поэтому вместо него применяется прочерк.

Третий шаблон соответствует любому массиву из трех элементов. При этом его элементы передаются в переменные first, second и third:

case [first, second, third]:

print(f"{first}, {second}, {third}")

В данном случае для соответствия любому из шаблонов массив должен был иметь три элемента. Но также можно определять шаблоны для массивов разной длины:

def print_people(people):

match people:

case [_]:

print("Массив из одного элемента")

case [_, _]:

print("Массив из двух элементов")

case [_, _, _]:

print("Массив из трех элементов")

case _:

print("Непонятно")

print_people(["Tom"])                   # Массив из одного элемента

print_people(["Tom", "Sam"])            # Массив из двух элементов

print_people(["Tom", "Sam", "Bob"])     # Массив из трех элементов

print_people("Tom")                     # Непонятно

Массивы неопределенной длины

Если необходимо сравнивать выражение с массивом неопределенной длины, то можно определить значения/переменные только для обязательных элементов массива, а на необязательные ссылаться с помощью символа * (звездочки):

def print_people(people):

match people:

case [first, *other]:

print(f"First: {first}  Other: {other}")

print_people(["Tom"])                   # First: Tom  Other: []

print_people(["Tom", "Sam"])            # First: Tom  Other: ["Sam"]

print_people(["Tom", "Sam", "Bob"])     # First: Tom  Other: ["Sam", "Bob"]

В примере выше применяется параметр *other, который соответствует всем остальным элементам. То есть шаблон [first, *other] соответствует любому массиву, который имеет как минимум один элемент, и этот элемент будет помещаться в параметр first. Все остальные элементы помещаются в параметр other, который представляет массив значений.

Если нам параметр с символом * (other) не важен, но мы по прежнему хотим, чтобы шаблон соответствовал массиву с одним и большим количеством элементов, мы можем использовать подшаблон *_:

def print_people(people):

match people:

case [first, *_]:

print(f"First: {first}")

print_people(["Tom"])                   # First: Tom

print_people(["Sam", "Tom"])            # First: Sam

print_people(["Bob", "Sam", "Tom"])     # First: Bob

Альтернативные значения

Если необходимо, чтобы элемент массива соответствовал набору значений, то эти значения можно перечислить через вертикальную черту:

def print_people(people):

match people:

case ["Tom" | "Tomas" | "Tommy", "Sam", "Bob"]:

print("default people")

case [first, second, third]:

print(f"{first}, {second}, {third}")

print_people(["Tom", "Sam", "Bob"])         # default people

print_people(["Tomas", "Sam", "Bob"])       # default people

print_people(["Alice", "Bill", "Kate"])     # Alice, Bill, Kate

В данном случае первый шаблон соответствует массиву из трех элементов, где первый элемент равен или "Tom", или "Tomas", или "Tommy".

Также можно задать альтернативные значения для отдельных элементов, но и альтернативные массивы:

def print_people(people):

match people:

case ["Tom", "Sam", "Bob"] | ["Tomas", "Sam", "Bob"]:

print("Tom/Tomas, Sam, Bob")

case [first, second, third]:

print(f"{first}, {second}, {third}")

print_people(["Tom", "Sam", "Bob"])         # Tom/Tomas, Sam, Bob

print_people(["Tomas", "Sam", "Bob"])       # Tom/Tomas, Sam, Bob

print_people(["Alice", "Bill", "Kate"])     # Alice, Bill, Kate

В данном случае первый шаблон будет соответствовать двум массивам: ["Tom", "Sam", "Bob"] и ["Tomas", "Sam", "Bob"]