Содержание:
- Генерация последовательностей и массивов с помощью лямбда-выражений
- Запрос Where: Фильтрация последовательностей
- Запрос Select: Проекция последовательностей
- Сортировка или упорядочивание последовательностей
- Вычисление скаляра
- Вычисление логического значения
- Сцепление и операции над множествами
- Объединение, разделение
- Преобразование в контейнер
- Поэлементные операции
- Действия над элементами
Генерация последовательностей и массивов с помощью лямбда-выражений
Для генерации последовательностей при помощи лямбда-выражений используется функция SeqGen
в следующих модификациях:
SeqGen(count: integer; f: integer -> T): sequence of T;
SeqGen(count: integer; first: T; next: T -> T): sequence of T;
SeqGen(count: integer; first,second: T; next: (T,T) -> T): sequence of T;
SeqWhile(first: T; next: T -> T; pred: T -> boolean): sequence of T;
SeqWhile(first,second: T; next: (T,T) -> T; pred: T -> boolean): sequence of T;
begin var sq:=SeqGen(5,x->x+1); sq.println; // 1 2 3 4 5 end. |
begin var sq:=SeqGen(5, 4, x->x+1); sq.println; // 4 5 6 7 8 end. |
begin var sq:=SeqGen(5, 1,3, (x,y)->x+y); sq.println; // 1 3 4 7 11 end. |
Выполнение:
var n:=readInteger; var sq3:=SeqGen(n,1,1,(x,y)->x+y); sq3.println(); |
begin var sq:=seqWhile(2, x -> x * 2, x -> x <= 1024); sq.println; // 2 4 8 16 32 64 128 256 512 1024 end. |
begin var sq := seqWhile(1, 1, (x, y)-> x + y, x -> x <= 1000); sq.println; // 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 end. |
То же для массивов с заменой Seq
на Arr
– возвращают array of T
N
четных чисел, начиная с 10 (SeqGen
)
Результат:
Enter n >> 7 10 12 14 16 18 20 22
Результат:
1 3 9 27 81 243 729 2187 6561 19683
Результат:
2 1 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.0009765625 0.00048828125 0.000244140625 0.0001220703125
Результат:
2017 2012 2007 2002 1997 1992 1987 1982 1977 1972
N
чисел, заданных итерационным процессом: а1=5, ак=ак-1/2-1, к=2,3,…
Результат:
Enter n >> 9 5 1.5 -0.25 -1.125 -1.5625 -1.78125 -1.890625 -1.9453125 -1.97265625
Выполнение:
var sq5:=SeqGen(n,2,x->(x+1)*x); sq5.println(); |
Результат:
>> 12 1 2 4 8 16 32 64 128 256 512 1024 2048
Результат:
>> 8 1 2 1.5 1.75 1.625 1.6875 1.65625 1.671875
Отрезание кусков последовательностей
Take(count)
TakeLast(count)
Skip(count)
SkipLast(count)
TakeWhile(T -> boolean)
TakeWhile((T, integer) -> boolean)
SkipWhile(T -> boolean)
SkipWhile((T, integer) -> boolean)
Slice(from,step[,count]: integer): sequence of T;
Distinct
Reverse
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Take(2); // 1 2 s1.Println; end. |
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Skip(2); // 3 4 5 6 7 8 9 10 s1.Println; end. |
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Skip(3)+s.Take(3); // 4 5 6 7 8 9 10 1 2 3 s1.Println; end. |
Выбор только неповторяющихся элементов
var a:=Seq(1,3,1,4,1,5); a.Distinct.Print; // 1 3 4 5 |
Реверсирует последовательность
var a:=Seq(1,3,1,4,1,5); a.Reverse.Print; // 5 1 4 1 3 1 |
Генерация бесконечных последовательностей
Cycle()
Repeat
Step
Iterate
Повторение блока последовательности:
Seq(1,2,10,5).Cycle().Take(15).Println; // 1 2 10 5 1 2 10 5 1 2 10 5 1 2 10 |
Take
используется для ограниченияБесконечная последовательность из указанного числа:
var q:=55.Repeat.Take(10).Println; // 55 55 55 55 55 55 55 55 55 55 |
Генерация бесконечной последовательности с шагом:
var q:=5.Step(2).Take(10).Println; // 5 7 9 11 13 15 17 19 21 23 |
Генерация бесконечной последовательности при помощи лямбда-функции:
var q:=10.Iterate(x -> x-2).Take(10).Println; // 10 8 6 4 2 0 -2 -4 -6 -8 |
Seq(1,2,10,5).Cycle()
). Вывести по 100 элементов каждойЗапрос Where: Фильтрация последовательностей
Запросы позволяют выполнять обработку последовательностей наиболее эффективным образом.
Where(T -> boolean)
Where((T, integer) -> boolean)
var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Where(x->x mod 2=0); // 2 4 6 8 10 |
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Where((x,i)->i mod 2=0); // 1 3 5 7 9 s1.Println; end. |
Здесь x
— это элемент, а i
— индекс элемента. Т.о. отбираются элементы с четными индексами
а) четные; б) кратные 5; в) отрицательные; д) нечетные
Выполнение:
writeln('Четные '); var s1:=sq.Where(x->x mod 2 =0).Println; s1:=sq2.Where(x->x mod 2 =0).Println; s1:=sq3.Where(x->x mod 2 =0).Println; s1:=sq5.Where(x->x mod 2 =0).Println; s1:=sq6.Where(x->x mod 2 =0).Println; writeln('Кратные 5 '); var s2:=sq2.Where(x->x mod 5 =0).Println; s2:=sq3.Where(x->x mod 5 =0).Println; // ... writeln('Отрицательные '); s2:=sq2.Where(x-> x < 0 ).Println; // ... writeln('Нечетные '); s1:=sq.Where(x->x mod 2 <>0).Println; s1:=sq2.Where(x->x mod 2 <>0).Println; // ... |
Where и отрезание кусков последовательности
SeqWhile
). Выберите элементы, кратные 3 и оставьте из них 10 чиселВыполнение:
seqWhile(1,x->x + 2,x->x<=10000).Where(x->x mod 3=0).take(100).Println; |
Выполнение:
begin var a:=seqRandomInteger(10,-10,10); var a1:=readInteger; var a2:=readInteger; assert(a1<a2); assert(a1>=1); var b1:=a.Skip(a1).take(a2-a1+1).where(x->x<0).Sum; println('результат: ',b1); end. |
Запрос Select: Проекция последовательностей
При использовании проекции преобразуется каждый элемент последовательности (в отличие от where
)
Select(T -> TRes)
Select((T, integer) -> TRes)
SelectMany(T -> sequence of TRes)
SelectMany((T, integer) -> sequence of TRes)
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Select(x->x*x); // 1 4 9 16 25 36 49 64 81 100 s1.Println; end. |
Комбинация проекции и фильтрации:
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Where(x -> x mod 2 = 0).Select(x->x*x); // 4 16 36 64 100 s1.Println; end. |
Select и отрезание кусков последовательности
Skip()
Результат:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 Результат: 7921 20736 54289 142129 372100 974169 2550409 6677056 17480761 45765225 119814916 313679521 821223649 -2144975872 1333783329
Выборка не только по элементу, но и по его индексу
Пример печати квадратов элементов с их индексами (в виде кортежей):
begin var s:=seqGen(10,x->x+1); // 1 2 3 4 5 6 7 8 9 10 var s1:=s.Select((x,i)->(i+1,x*x)); s1.Println;//(1,1) (2,4) (3,9) (4,16) (5,25) (6,36) (7,49) (8,64) (9,81) (10,100) end. |
Сортировка или упорядочивание последовательностей
Sorted
SortedDescending
OrderBy(T -> TKey)
OrderByDescending(T -> TKey)
ThenBy(T -> TKey)
ThenByDescending(T -> TKey)
var s:=Seq(('Ivanov',20,1),('Petrov',19,2),('Popov',21,1)); s.OrderBy(x->x[0]).Println; // (Ivanov,20,1) (Petrov,19,2) (Popov,21,1) s.OrderBy(x->x[1]).Println; // (Petrov,19,2) (Ivanov,20,1) (Popov,21,1) |
Пример: Данная функция может быть использована, например, для поиска k максимумов в массиве:
begin var a:=Arr(1,3,5,2,7,9,0); var k:=3; a.OrderByDescending(x->x).Distinct.Take(k).Print; // 9 7 5 end. |
Выполняет дополнительное упорядочение элементов последовательности в порядке возрастания ключа и возвращает отсортированную последовательность. T -> TKey — функция, проектирующая элемент на ключ.
begin var a := Arr(('Иванов', 20), ('Попов', 21), ('Иванов', 18), ('Авилов', 28), ('Иванов', 25)); a.OrderBy(t -> t[0]).ThenBy(t -> t[1]).Println; // (Авилов,28) (Иванов,18) (Иванов,20) (Иванов,25) (Попов,21) end. |
Вычисление скаляра
Count([T -> boolean]): integer
Average: double
Average(T -> числовой_тип): double
Sum: числовой_тип
Sum(T -> числовой_тип): числовой_тип
Max: T
Max(T -> TRes): TRes
Min: T
Min(T -> TRes): TRes
MinBy(selector: T -> TKey): T
MaxBy(selector: T -> TKey): T
Aggregate((T, T) -> T): T
- Классический вариант нахождения суммы:
- Теперь используем функцию:
Aggregate(TRes seed, (TRes, T) -> TRes): TRes
JoinIntoString([delim: string]): string;
var a:=Arr(1,2,3,4,5); var b:=a.Count(x->x mod 2 <>0); // 3 нечетных элемента |
Count
— это фильтр (как Where
), который считает кол-во нечетных элементов.Пример вывода среднего возраста студентов:
var students:=Seq(('Ivanov',20,1),('Petrov',19,2),('Popov',21,1)); var i:=students.Average(x->x[1]); // 20 |
Пример:Дан массив a: 1,3,5,2,7,9,0. Необходимо найти три первых максимума. Максимумы не должны быть равны друг другу:
begin var a:=Arr(1,3,5,2,7,9,0); var max:=a.Max; var max1:=a.Where(x->x<max).Max; var max2:=a.Where(x->x<max1).Max; print(max,max1,max2); // 9 7 5 end. |
Пример вывода минимального показателя рейтинга студентов:
var students:=Seq(('Ivanov',20,40),('Petrov',19,25),('Popov',21,35)); var i:=students.Min(x->x[2]); // 25 |
Это модификация обычной функции Min. Выводит всю запись:
var students:=Seq(('Ivanov',20,40),('Petrov',19,25),('Popov',21,35)); var i:=students.MinBy(x->x[2]); // (Petrov,19,25) |
Average
, Sum
, Max
и Min
— это не фильтр, а проекция (как Select
) Выполнение:
println(seqWhile(1,1,(x,y)->x+y,x->x div 1000=0) .where (x-> (x>100)and(x<=999)and (x mod 2 =0)).average); |
Примерный вывод:
последовательность: 1 1 2 3 5 8 13 21 34 55 89 сумма: 232
count
с условием.
Примерный вывод:
3
where
и count
с условием.
Примерный вывод:
1 5 7 1 4
Выполнение:
var sq11:=Arr(1,2,3,4,5,6,7,-10,-12); println(sq11.Where(x->x mod 2=0).max); println(sq11.Where(x->x mod 2<>0).min); |
Выполнение:
begin var g: sequence of integer; g:=Seq(23,39,77,62); println(g.select(x->x mod 10).Sum); end. |
Выполнение:
var sq12:=SeqGen(125,1,1,(x,y)->x+y).Where (x-> x mod 2<>0).Select(x->x*x).Take(20); println(sq12); |
round()
) из данного набора, а также сумму всех округленных чисел. Для вывода итоговой последовательности использовать проекцию Select
, а для подсчета суммы — проекциюSum
, и две переменные для хранения результатов.
Результат:
1 4 5 2 7 10 1 30
Агрегация – это наиболее распространенный метод сворачивания последовательности в скалярную.
Aggregate
— функция-накопитель. Работает как сумматор, произведение элементов, конкатенация строк.
✍ Решение:
var q:=Seq(3,9,7,2); var s:=0; foreach var x in q do s+=x; print(s); //21 |
var q:=Seq(3,9,7,2); print(q.Aggregate(0,(s,x) -> s+x)); // 21 |
Пример: выполнить произведение элементов последовательности:
var q:=Seq(3,9,7,2); print(q.Aggregate(1,(p,x) -> p*x)); // 378 |
Пример: выполнить конкатенацию элементов последовательности:
var q:=Seq('a','b','c'); print(q.Aggregate('',(s,x) -> s+x)); // abc |
Эти методы еще называются методами свертки последовательностей в скаляр (fold).
Пример свертки в строку:
var a:=Arr(1,3,5); // массив var s:=a.JoinIntoString.Println; // 1 3 5 - строка |
Select
и функцию Aggregate
.
Результат:
1 9 25 4 49 81 0 169
Вычисление логического значения
All(T -> boolean)
Any(T -> boolean)
Contains(x: T) // можно x in s
SequenceEqual(second: sequence of T)
Пример: Доказать, что в последовательности все числа нечетные:
begin var sq:=Seq(1,3,5,2,7,9,0); print(sq.All(x->x mod 2 <>0)); // False end. |
Пример: Есть ли в последовательности числа большие 7:
begin var sq:=Seq(1,3,5,2,7,9,0); print(sq.Any(x->x > 7)); // True end. |
Пример: Доказать, что в последовательности все числа различны:
begin var sq:=Seq(1,3,5,2,7,9,0); print(sq.SequenceEqual(sq.Distinct)); // True end. |
В примере сравнивается исходная последовательность с то же последовательностью, только без повторений.
True
; в противном случае вывести False
.
Результат:
-3 4 -4 -4 5 -4 -5 0 -2 0 True
True
; в противном случае вывести False
.
Результат:
>> -3 -2 -1 -4 4 -5 5 2 -1 -4 4 True
K
, то вывести True
; в противном случае вывести False
. Использовать функцию Contains()
.
Результат:
>> -3 -2 -1 -4 4 -5 5 2 -1 -4 4 False
Сцепление и операции над множествами
Concat(second: sequence of T) // можно s1 + s2 или a1 + a2
Union(second: sequence of T)
Intersect(second: sequence of T)
Except(second: sequence of T)
begin var a:=Seq(1,2,3,4); var b:=Seq(3,4,5); var sq:=a.Concat(b).Println; // 1 2 3 4 3 4 5 end. |
begin var a:=Seq(1,2,3,4); var b:=Seq(3,4,5); var sq:=a.Union(b).Println; // 1 2 3 4 5 end. |
begin var a:=Seq(1,2,3,4); var b:=Seq(3,4,5); var sq:=a.Intersect(b).Println; // 3 4 end. |
begin var a:=Seq(1,2,3,4); var b:=Seq(3,4,5); var sq:=a.Except(b).Println; // 1 2 end. |
Выполнение:
... r1.Take(25).Union(r4.Take(40)).distinct.Println; r2.Take(30).Intersect(r4.Take(20)).distinct.Println; ... |
Except()
Объединение, разделение
Zip(second: sequence of T, (T,T)->T1): sequence of T1
Cartesian(second: sequence of T1): sequence of (T,T1);
ZipTuple(second: sequence of T1): sequence of (T,T1);
sequence of (T,T1).UnZipTuple: (sequence of T,sequence of T1);
SplitAt(ind: integer): (sequence of T,sequence of T);
Partition(cond: T->boolean): (sequence of T,sequence of T);
Interleave(second: sequence of T): sequence of T;
Numerate([from: integer]): sequence of (integer,T);
Tabulate(F: T->T1): sequence of (T,T1);
Pairwise: sequence of (T,T);
Пример: сложение элементов двух последовательностей:
var a:=Seq(3,9,7,13,2,4,2); var b:=Seq(2,4,7,1,5,4); var sq:=a.Zip(b,(xa,xb)->(xa+xb)).Println; // 5 13 14 14 7 8 |
Проблема: В последовательностях нет индексов элементов, и в каждый момент времени доступен только 1 элемент, т.о. не возможно сравнение предыдущего элемента со следующим.
Выполнение:
begin var a:=Seq(3,9,7,13,2,4); var b:=a.Skip(1); // [9,7,13,2,4] // Теперь можно сравнить две последовательности var sq:=a.Zip(b,(xa,xb)->(xa,xb)).Println; // (3,9) (9,7) (7,13) (13,2) (2,4) println(sq.Count(x->x[0]>x[1])); // 2 // ИЛИ вывод этих элементов sq.Where(x->x[0]>x[1]).Select(x->x[1]).Println; end. |
1 Вариант: разность элементов последовательностей и поиск минимума
Выполнение:
begin var a:=Seq(3,9,7,13,2,4,2); var b:=Seq(2,4,7,1,5,4); var sq:=a.Zip(b,(xa,xb)->(xa-xb)).Println; // 1 5 0 12 -3 0 PrintLn(sq.Min) // -3 end. |
2 Вариант: разность последовательностей и поиск минимума
Выполнение:
begin var a:=Seq(3,9,7,13,2,4,2); var b:=Seq(2,4,7,1,5,4); var sq:=a.Except(b).Println; // 3 9 13 PrintLn(sq.Min) // 3 end. |
Декартово произведение массивов в одном массиве.
begin var x1:=Arr('Ivanov','Petrov','Sidorov'); var x2:=Arr('Pizza','hamburger','sweets'); x1.Cartesian(x2).Println; { (Ivanov,Pizza) (Ivanov,hamburger) (Ivanov,sweets) (Petrov,Pizza) (Petrov,hamburger) (Petrov,sweets) (Sidorov,Pizza) (Sidorov,hamburger) (Sidorov,sweets)} end. |
Кортежное объединение последовательностей.
begin var a:=Seq(1,3,5,2,8); var b:=Seq(9,7,2,3,8,4); a.ZipTuple(b).Println; // (1,9) (3,7) (5,2) (2,3) (8,8) end. |
Выполнение:
// ??? неверное решение begin var r: sequence of integer; var t1,t2,t3: sequence of integer; r:=range(85,95); // 85,86,87,88,89,90,91,92,93,94,95] println(r); t1:=r.Select(x-> x mod 10).Println;//5 6 7 8 9 0 1 2 3 4 5 t2:=r.Select(x-> x div 10).Println; //8 8 8 8 8 9 9 9 9 9 9 var sq:=t1.Zip(t2,(xa,xb)->(xa,xb)).Println; //(5,8) (6,8) (7,8) (8,8) (9,8) (0,9) (1,9) (2,9) (3,9) (4,9) (5,9) t1.ZipTuple(t2).Println;//(5,8) (6,8) (7,8) (8,8) (9,8) (0,9) (1,9) (2,9) (3,9) (4,9) (5,9) end. |
Деление последовательности по условию.
begin var a:=Range(-5,5).Println; // -5 -4 -3 -2 -1 0 1 2 3 4 5 (var q1,var q2):= a.Partition(x->x>=0); Println (q1,q2) // [0,1,2,3,4,5] [-5,-4,-3,-2,-1] end. |
Здесь используется кортежное присваивание.
Выполнение:
begin var a:=Seq(1,2,3,4,5,6); (var q1,var q2):=a.Partition(x->x mod 2 = 0); println(q1,q2) // [2,4,6] [1,3,5] end. |
Нумерация некоторой последовательности:
begin var a:=Seq(11,12,1,3,7); a.Numerate.Println // (1,11) (2,12) (3,1) (4,3) (5,7) end. |
Преобразование в контейнер
-
ToArray: array of T;
ToHashSet: HashSet
; ToSortedSet: SortedSet
;
Поэлементные операции
First([T -> boolean])
Last([T -> boolean])
Single([T -> boolean])
ElementAt(integer index)
Взять 1-й элемент:
var a:=Arr(1,3,5); print(a.First); // 1 |
Взять k-й элемент:
var a:=Arr(1,3,5); print(a.ElementAt(2)); // 5 |
Результат:
-5 4 5 3 -3 0 5 -2 -3 3 5 -4
D
(однозначное целое число) и целочисленный массив A
. Вывести первый положительный элемент массива A
, оканчивающийся цифрой D
. Если требуемых элементов в массива A
нет, то вывести 0.
Результат:
2 38 29 22 17 10 39 31 39 50 44 22
Действия над элементами
ForEach(action: T -> ())
У вас ошибка в примере программы после задания 13. Там при каждом обращении к случайной последовательности она генерируется снова.
begin
var g,j: sequence of integer;
g:=seqRandomInteger(10,10,1000);
j:=g.Select(x->x mod 10);
writeln(j.sum);
end.
{929 857 829 22 367 342 864 603 309 464
8 1 6 0 8 9 9 5 5 3
44
}
Спасибо! Исправлено