Методы последовательностей

Последовательности в PascalABC.NET имеют большое число методов для поиска, отбора, преобразования, сортировки, группировки и обработки данных. Многие из этих методов принимают лямбда-выражения как параметры.

Методы последовательностей можно применять не только к значениям типа sequence of T, но и к массивам, спискам и множествам, поскольку все коллекции являются последовательностями.

Количество, сумма и среднее

Методы Count, Sum и Average возвращают количество элементов, их сумму и среднее арифметическое для числовых последовательностей.

begin
  var a := [3,8,1,6,4];

  Println(a.Count);
  Println(a.Sum);
  Println(a.Average);
end.

Результат:

5
22
4.4

Минимум и максимум

Методы Min и Max находят минимальный и максимальный элементы последовательности.

begin
  var s: sequence of integer := Lst(7,2,9,4,5);

  Println(s.Min);
  Println(s.Max);
end.

Результат:

2
9

Произведение элементов

Метод Product вычисляет произведение всех элементов числовой последовательности.

begin
  var s := SetOf(1,2,3,4,5);

  Println(s.Product);
end.

Результат:

120

Первый и последний элементы

Методы First и Last возвращают первый и последний элементы последовательности.

begin
  var a := [3,8,1,6,4];

  Println(a.First);
  Println(a.Last);
end.

Результат:

3
4

Проверка существования элемента по условию

Метод Any проверяет, существует ли хотя бы один элемент, удовлетворяющий лямбда-условию.

begin
  var a: sequence of integer := [3,8,1,6,4];

  Println(a.Any(x -> x > 7));
  Println(a.Any(x -> x < 0));
end.

Результат:

True
False

Проверка всех элементов

Метод All проверяет, удовлетворяют ли все элементы последовательности заданному условию.

begin
  var a: sequence of integer := [2,4,6,8,10];

  Println(a.All(x -> x mod 2 = 0));
  Println(a.All(x -> x > 5));
end.

Результат:

True
False

Проверка отсутствия элементов

Метод NoneOf проверяет, что ни один элемент последовательности не удовлетворяет заданному условию.

begin
  var a: sequence of integer := [2,4,6,8,10];

  Println(a.NoneOf(x -> x < 0));
  Println(a.NoneOf(x -> x > 5));
end.

Результат:

True
False

Количество элементов по условию

Метод Count с лямбда-условием подсчитывает элементы, удовлетворяющие заданному критерию.

begin
  var a := Arr(1..10);

  Println(a.Count(x -> x mod 2 = 0));
end.

Результат:

5

Отбор элементов

Метод Where оставляет только элементы, для которых лямбда-условие возвращает True, и возвращает последовательность.

begin
  var a := Arr(1..10);

  var s: sequence of integer := a.Where(x -> x mod 2 = 0);
  s.Println;
end.

Результат:

2 4 6 8 10

Преобразование элементов

Метод Select применяет лямбда-преобразование к каждому элементу последовательности.

begin
  var a := Arr(1..5);

  var s: sequence of integer := a.Select(x -> x*x);
  s.Println;
end.

Результат:

1 4 9 16 25

Преобразование к другому типу

Select может создавать последовательность элементов другого типа.

begin
  var a := Arr(1..5);

  var s: sequence of string := a.Select(x -> $'№{x}');
  s.Println;
end.

Результат:

№1 №2 №3 №4 №5

Проекция составных объектов

С помощью Select можно извлекать отдельные части составных элементов.

begin
  var people: array of (string,integer) := [
    ('Анна',21),
    ('Борис',18),
    ('Вера',25)
  ];

  people.Select(p -> p.Item1).Println;
end.

Результат:

Анна Борис Вера

Отбор и преобразование

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

begin
  var a := Arr(1..10);

  a.Where(x -> x mod 2 = 0)
   .Select(x -> x*x)
   .Println;
end.

Результат:

4 16 36 64 100

Минимальный элемент по проекции

Метод MinBy возвращает элемент, для которого значение заданной проекции минимально, а метод MaxBy — элемент, для которого значение заданной проекции максимально.

begin
  var words := ['Pascal','cat','programming','code'];

  words.MinBy(s -> s.Length).Println;
  words.MaxBy(s -> s.Length).Println;
end.

Результат:

cat
programming

Сортировка по возрастанию и убыванию

Методы Order и OrderDescending сортируют элементы по возрастанию и убыванию.

begin
  var a := [7,2,9,4,1,6];

  var s: sequence of integer := a.Order;
  s.Println;
  a.OrderDescending.Println;
end.

Результат:

1 2 4 6 7 9
9 7 6 4 2 1

Сортировка по ключу

Методы OrderBy и OrderByDescending сортируют элементы по значению, вычисляемому лямбда-проекцией.

begin
  var words := ['pear','watermelon','fig','apple'];

  words.OrderBy(s -> s.Length).Println;
  words.OrderByDescending(s -> s.Length).Println;
end.

Результат:

fig pear apple watermelon
watermelon apple pear fig

Сортировка по нескольким ключам

Метод ThenBy задаёт дополнительный ключ сортировки для элементов с одинаковым значением первого ключа.

begin
  var people := [
    ('Анна',20),
    ('Борис',18),
    ('Вера',20),
    ('Алексей',18)
  ];

  people
    .OrderBy(p -> p.Item2)
    .ThenBy(p -> p.Item1)
    .Println;
end.

Результат:

(Алексей,18) (Борис,18) (Анна,20) (Вера,20)

Удаление повторов

Метод Distinct оставляет только различные элементы последовательности.

begin
  var a := [3,1,2,3,2,4,1,3];

  var s: sequence of integer := a.Distinct;
  s.Println;
end.

Результат:

3 1 2 4

Первые элементы

Метод Take возвращает заданное количество элементов с начала последовательности.

begin
  var a := Arr(1..10);

  a.Take(4).Println;
end.

Результат:

1 2 3 4

Пропуск первых элементов

Метод Skip пропускает заданное количество элементов с начала последовательности.

begin
  var a := Arr(1..10);

  a.Skip(6).Println;
end.

Результат:

7 8 9 10

Часть последовательности

Сочетание Skip и Take позволяет выбрать часть последовательности.

begin
  var a := Arr(1..10);

  a.Skip(3).Take(4).Println;
end.

Результат:

4 5 6 7

Последние элементы

Метод TakeLast возвращает заданное количество элементов с конца последовательности.

begin
  var a := Arr(1..10);

  a.TakeLast(3).Println;
end.

Результат:

8 9 10

Пропуск последних элементов

Метод SkipLast возвращает последовательность без заданного количества последних элементов.

begin
  var a := Arr(1..7);

  a.SkipLast(3).Println;
end.

Результат:

1 2 3 4

Выбор элементов с начала по условию

Метод TakeWhile берёт элементы с начала последовательности, пока выполняется заданное условие.

begin
  var a := [8,7,6,4,2,9,1];

  a.TakeWhile(x -> x > 3).Println;
end.

Результат:

8 7 6 4

Пропуск элементов с начала по условию

Метод SkipWhile пропускает элементы с начала последовательности, пока выполняется заданное условие.

begin
  var a := [8,7,6,4,2,9,1];

  a.SkipWhile(x -> x > 3).Println;
end.

Результат:

2 9 1

Нумерация элементов

Метод Numerate добавляет к каждому элементу его порядковый номер; по умолчанию нумерация начинается с единицы.

begin
  var words := ['red','green','blue'];

  words.Numerate.Println;
end.

Результат:

(1,red) (2,green) (3,blue)

Нумерацию можно начать с другого числа.

begin
  var words := ['red','green','blue'];

  words.Numerate(0).Println;
end.

Результат:

(0,red) (1,green) (2,blue)

Вывод элементов по строкам

Метод PrintLines выводит каждый элемент последовательности с новой строки.

begin
  var words := ['Pascal','Python','C#'];

  words.PrintLines;
end.

Результат:

Pascal
Python
C#

Вывод с преобразованием

PrintLines может принимать лямбда-преобразование, задающее вид выводимого элемента.

begin
  var a := Arr(1..5);

  a.PrintLines(x -> $'{x}² = {x*x}');
end.

Результат:

1² = 1
2² = 4
3² = 9
4² = 16
5² = 25

Подсчёт частот

Метод EachCount возвращает словарь пар (элемент, количество) для всех различных элементов последовательности.

begin
  var a := [3,1,2,3,2,3,1];

  a.EachCount.Println;
end.

Результат:

(3,3) (1,2) (2,2)

Частоты символов и слов

EachCount удобно использовать для построения частотного словаря символов и слов.

begin
  var s := 'abracadabra';
  var s1 := 'one two one three one four four four one';

  s.EachCount.Println;
  s1.EachCount.Println;
end.

Результат:

(a,5) (b,2) (r,2) (c,1) (d,1)
(one,4) (two,1) (three,1) (four,3)

Группировка элементов

Метод GroupBy разбивает последовательность на группы с одинаковым значением заданного ключа.

begin
  var a := Arr(1..9);

  a.GroupBy(x -> x mod 3).Println;
end.

Результат:

[1,4,7] [2,5,8] [3,6,9]

Группировка слов по длине

В качестве ключа группировки можно использовать лямбда-проекцию.

begin
  var words := ['cat','book','dog','table','code','sun'];

  foreach var g in words.GroupBy(s -> s.Length) do
  begin
    Print($'{g.Key}:');
    g.Println;
  end;
end.

Результат:

3: cat dog sun
4: book code
5: table

Преобразование вложенной последовательности в плоскую

Метод Flatten объединяет внутренние последовательности в одну последовательность элементов.

begin
  var a := [
    [1,2,3],
    [4,5],
    [6,7,8]
  ];

  a.Flatten.Println;
end.

Результат:

1 2 3 4 5 6 7 8

Чередование двух последовательностей

Метод Interleave поочерёдно берёт элементы из двух последовательностей.

begin
  var a := [1,2,3];
  var b := [10,20,30];

  a.Interleave(b).Println;
end.

Результат:

1 10 2 20 3 30

Пары соседних элементов

Метод Pairwise создаёт кортежи из соседних элементов последовательности.

begin
  var a := [3,8,5,10];

  a.Pairwise.Println;
end.

Результат:

(3,8) (8,5) (5,10)

Преобразование соседних пар

Pairwise может принимать лямбда-выражение, которое применяется к каждой паре соседних элементов.

begin
  var a := [3,8,5,10];

  a.Pairwise((x,y) -> y-x).Println;
end.

Результат:

5 -3 5

Соединение двух последовательностей

Метод Zip соединяет элементы с одинаковыми позициями в последовательность кортежей.

begin
  var names := ['Анна','Борис','Вера'];
  var ages := [21,18,25];

  names.Zip(ages).Println;
end.

Результат:

(Анна,21) (Борис,18) (Вера,25)

Соединение с преобразованием

Zip может сразу применять лямбда-выражение к соответствующим элементам двух последовательностей.

begin
  var a := [1,2,3,4];
  var b := [10,20,30,40];

  a.Zip(b,(x,y) -> x+y).Println;
end.

Результат:

11 22 33 44

Агрегирование

Метод Aggregate последовательно объединяет элементы с помощью заданной операции.

begin
  var digits := [1,2,3,4,5];

  Println(digits.Aggregate((n,d) -> 10*n+d));
end.

Результат:

12345

Цепочка методов

Методы последовательностей можно объединять в цепочки, последовательно выполняя отбор, удаление повторов, сортировку и преобразование элементов.

begin
  var a := [7,2,9,4,2,6,8,4];

  a
    .Where(x -> x mod 2 = 0)
    .Distinct
    .Order
    .Select(x -> x*x)
    .Println;
end.

Результат:

4 16 36 64