Паттерны списков и кортежей

Последнее обновление: 13.05.2023

Паттерны списков

Паттерны списков позволяют сопоставлять выражения со списками. Например, полное совпадение со списком:

void main() {
    
    print(getNumber([1, 2, 3, 4, 5]));  // 1
    print(getNumber([1, 2]));           // 3
    print(getNumber([]));               // 4
    print(getNumber([1, 2, 5]));        // 5
}

int getNumber(List<int> values) {
    switch(values)
    {
        case [1, 2, 3, 4, 5]:  return 1;
        case [1, 2, 3]:  return 2;
        case [1, 2]:  return 3;
        case []:  return  4;
        default: return 5;
    }
}

Подстановка _

С помощью паттерна _ можно обозначить одиночный элемент, который имеет любое значение. Например, паттерн [2, _, 5] соответствует любому списку из трех элементов, в котором между 2 и 5 располагается произвольное значение. А паттерн [_, _] соответствует любому списку из двух произвольных элементов. Несколько примеров:

void main() {
    
    print(getNumber([2, 3, 5]));    // 1
    print(getNumber([2, 4, 6]));    // 2
    print(getNumber([1, 2, 5]));    // 3
    print(getNumber([1, 2, 3]));    // 4
    print(getNumber([]));           // 5
}

int getNumber(List<int> values) {
    switch(values)
    {
        case [2, _, 5]: return 1;
        case [2, _, _]: return 2;
        case [_, _, 5]: return 3;
        case [_, _, _]: return 4;
        case _: return 5;
    }
}

Выражение case _ фактически аналогично выражению default, которое задает вариант по умолчанию, если предыдущие выражения case не соответствуют сравниваемому значению.

slice-паттерн

Для передачи произвольного количества элементов списка применяется slice-паттерн ... (три точки). Например, паттерн [1, 2, ..., 5] соответствует списку, в который начинается на 1, за которым идет 2, а последний элемент - 5. При этом между 2 и 5 может располагаться произвольное количество произвольных целых чисел. То есть паттерн [1, 2, ..., 5] будет соответствовать таким спискам как

[1, 2, 3, 4, 5]
[1, 2, 5]
[1, 2, 66, 77, 88, 5]

С помощью паттерна ... можно задавать произвольное количество элементов как в начале, так и в конце списка. Например, паттерн [2,...] представляет список, который начинается на 2. А паттерн [..., 5] представляет список, который заканчивается элементом 5. Паттерн [...] представляет массив, который содержит произвольное количество элементов. Например:

void main() {
    
    print(getNumber([2, 5]));           // 1
    print(getNumber([2, 3, 4, 5]));     // 1
    
    print(getNumber([2]));               // 2
    print(getNumber([2, 3, 4]));         // 2
    
    print(getNumber([3, 4, 5]));        // 3
    print(getNumber([5]));              // 3
    
    print(getNumber([]));               // 4
    print(getNumber([1]));              // 4
    print(getNumber([1, 2, 3]));        // 4
}

int getNumber(List<int> values) {

    switch(values)
    {
        case [2, ..., 5]: return 1;    // если первый элемент - 2, а последний - 5
        case [2,...]: return 2;        // если первый элемент - 2
        case [..., 5]: return 3;       // если последний элемент - 5
        case [...]: return 4;          // произвольное количество элементов
    }
}

slice-паттерн можно сочетать с символов подстановки _, например:

int getNumber(List<int> values) {

    switch(values)
    {
        case [_, ..., _]: return 1;
        case [...]: return 2;
    }
}

В данном случае паттерн [_, ..., _] предполагает список, который состоит как минимум из двух произвольных элементов, и между первым и последним элементром может находиться произвольное количество других элементов:

void main() {
    
    print(getNumber([1, 2, 3, 4]));     // 1
    print(getNumber([1, 2, 3]));        // 1
    print(getNumber([1, 2]));           // 1

    print(getNumber([1]));              // 2
    print(getNumber([]));               // 2
}

int getNumber(List<int> values) {

    switch(values)
    {
        case [_, ..., _]: return 1;
        case [...]: return 2;
    }
}

Паттерны кортежей

Паттерны кортежей позволяют сравнивать значения кортежей. Например, передадим в конструкцию switch кортеж с названием языка и времени дня и в зависимости от переданных данных возвратим определенное сообщение:

void main() {
    
    print(createMessage(("english", "morning")));   // Good morning
    print(createMessage(("german", "evening")));    // Guten Abend
    print(createMessage(("undefined", "")));        // Hello World
}

String createMessage((String, String) data) {
    switch(data)
    {
        case ("english", "morning"): 
            return "Good morning";
        case ("english", "evening"):
            return "Good evening";
        case ("german", "morning"): 
            return "Guten Morgen";
        case ("german", "evening"):
            return "Guten Abend";
        default: 
            return "Hello World";
    }
}

Здесь функция createMessage принимает кортеж record из двух элементов String. В конструкции switch сравниваем этот кортеж с некоторыми данными и в зависимости от результата сравнения возвращаем ту или иную строку.

Также в случае с кортежами, как и в случае со списками, можно применять паттерн _, который заменяет произвольный элемент кортежа:

void main() {
    
    print(createMessage(("english", "morning")));   // Good morning
    print(createMessage(("english", "evening")));    // Hello
    print(createMessage(("undefined", "")));        // Hello World
}

String createMessage((String, String) data) {
    switch(data)
    {
        case ("english", "morning"): 
            return "Good morning";
        case ("english", _):      // второй элемент не важен
            return "Hello";
        case _: 
            return "Hello World";
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850