Последовательности, подобные спискам, также представляют упорядоченную коллекцию значений. Однако элементы в последовательности или выражении последовательности вычисляются, когда это необходимо. Они не вычисляются сразу, и по этой причине они используются для представления бесконечных структур данных.
Определение последовательности
Последовательности определяются с использованием следующего синтаксиса —
seq { expr }
Например,
let seq1 = seq { 1 .. 10 }
Создание последовательностей и выражений последовательностей
Подобно спискам, вы можете создавать последовательности, используя диапазоны и значения.
Выражения последовательностей — это выражения, которые вы можете написать для создания последовательностей. Это может быть сделано —
- Указав диапазон.
- Указав диапазон с приращением или уменьшением.
- Используя ключевое слово yield для получения значений, которые становятся частью последовательности.
- С помощью оператора →.
Следующие примеры демонстрируют концепцию —
Пример 1
(* Sequences *) let seq1 = seq { 1 .. 10 } (* ascending order and increment*) printfn "The Sequence: %A" seq1 let seq2 = seq { 1 .. 5 .. 50 } (* descending order and decrement*) printfn "The Sequence: %A" seq2 let seq3 = seq {50 .. -5 .. 0} printfn "The Sequence: %A" seq3 (* using yield *) let seq4 = seq { for a in 1 .. 10 do yield a, a*a, a*a*a } printfn "The Sequence: %A" seq4
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
The Sequence: seq [1; 2; 3; 4; ...] The Sequence: seq [1; 6; 11; 16; ...] The Sequence: seq [50; 45; 40; 35; ...] The Sequence: seq [(1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64); ...]
Пример 2
Следующая программа печатает простые числа от 1 до 50 —
(* Recursive isprime function. *) let isprime n = let rec check i = i > n/2 || (n % i <> 0 && check (i + 1)) check 2 let primeIn50 = seq { for n in 1..50 do if isprime n then yield n } for x in primeIn50 do printfn "%d" x
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
Основные операции над последовательностью
В следующей таблице приведены основные операции с типом данных последовательности —
Значение | Описание |
---|---|
append: seq <‘T> → seq <‘ T> → seq <‘T> | Оборачивает два заданных перечисления как одно сцепленное перечисление. |
среднее значение: seq <^ T> → ^ T | Возвращает среднее значение элементов в последовательности. |
AverageBy: (‘T → ^ U) → seq <‘ T> → ^ U | Возвращает среднее значение результатов, полученных с помощью применения функции к каждому элементу последовательности. |
кеш: seq <‘T> → seq <‘ T> | Возвращает последовательность, которая соответствует кэшированной версии входной последовательности. |
приведение: IEnumerable → seq <‘T> | Обертывает свободно набранную Систему. Последовательность коллекций как типизированная последовательность. |
выберите: (опция ‘T →’ U) → seq <‘T> → seq <‘ U> | Применяет данную функцию к каждому элементу списка. Вернуть список, состоящий из результатов для каждого элемента, где функция возвращает Some . |
собирать: (‘T →’ Коллекция) → seq <‘T> → seq <‘ U> | Применяет данную функцию к каждому элементу последовательности и объединяет все результаты. |
сравнить с: (‘T →’ T → int) → seq <‘T> → seq <‘ T> → int | Сравнивает две последовательности, используя данную функцию сравнения, элемент за элементом. |
concat: seq <‘Collection> → seq <‘ T> | Объединяет данное перечисление перечислений в качестве единого каскадного перечисления. |
countBy: (‘T →’ Key) → seq <‘T> → seq <‘ Key * int> | Применяет функцию генерации ключа к каждому элементу последовательности и возвращает последовательность, дающую уникальные ключи и их количество вхождений в исходной последовательности. |
задержка: (единица измерения → seq <‘T>) → seq <‘ T> | Возвращает последовательность, которая построена из заданной отложенной спецификации последовательности. |
отчетливый: seq <‘T> → seq <‘ T> | Возвращает последовательность, которая не содержит повторяющихся записей в соответствии с общим сравнением хеша и равенства записей. Если элемент встречается в последовательности несколько раз, более поздние вхождения отбрасываются. |
DifferentBy: (‘T →’ Key) → seq <‘T> → seq <‘ T> | Возвращает последовательность, которая не содержит повторяющихся записей в соответствии с общим сравнением хэша и равенства для ключей, возвращаемых данной функцией генерации ключа. Если элемент встречается в последовательности несколько раз, более поздние вхождения отбрасываются. |
пусто: seq <‘T> | Создает пустую последовательность. |
точно один: seq <‘T> →’ T | Возвращает единственный элемент последовательности. |
существует: (‘T → bool) → seq <‘ T> → bool | Проверяет, удовлетворяет ли какой-либо элемент последовательности данному предикату. |
существует2: (‘T1 →’ T2 → bool) → seq <‘T1> → seq <‘ T2> → bool | Проверяет, удовлетворяет ли любая пара соответствующих элементов входных последовательностей данному предикату. |
фильтр: (‘T → bool) → seq <‘ T> → seq <‘T> | Возвращает новую коллекцию, содержащую только те элементы коллекции, для которых данный предикат возвращает true . |
найти: (‘T → bool) → seq <‘ T> → ‘T | Возвращает первый элемент, для которого данная функция возвращает true . |
findIndex: (‘T → bool) → seq <‘ T> → int | Возвращает индекс первого элемента, для которого данная функция возвращает true . |
свернуть: (‘State →’ T → ‘State) →’ State → seq <‘T> →’ State | Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Если входная функция — f, а элементы — i0 … iN, то эта функция вычисляет f (… (fs i0) …) iN. |
forall: (‘T → bool) → seq <‘ T> → bool | Проверяет, все ли элементы последовательности удовлетворяют данному предикату. |
forall2: (‘T1 →’ T2 → bool) → seq <‘T1> → seq <‘ T2> → bool | Тесты всех пар элементов, взятых из двух последовательностей, удовлетворяют данному предикату. Если одна последовательность короче другой, то остальные элементы более длинной последовательности игнорируются. |
groupBy: (‘T →’ Key) → seq <‘T> → seq <‘ Key * seq <‘T >> | Применяет функцию генерации ключа к каждому элементу последовательности и выдает последовательность уникальных ключей. Каждый уникальный ключ также содержит последовательность всех элементов, соответствующих этому ключу. |
head: seq <‘T> →’ T | Возвращает первый элемент последовательности. |
init: int → (int → ‘T) → seq <‘ T> | Создает новую последовательность, которая после повторения возвращает последовательные элементы, вызывая данную функцию, до заданного количества. Результаты вызова функции не сохраняются, то есть функция применяется повторно по мере необходимости для регенерации элементов. В функцию передается индекс генерируемого элемента. |
initInfinite: (int → ‘T) → seq <‘ T> | Создает новую последовательность, которая после повторения будет возвращать последовательные элементы, вызывая данную функцию. Результаты вызова функции не сохраняются, то есть функция будет применяться повторно по мере необходимости для регенерации элементов. В функцию передается индекс генерируемого элемента. |
isEmpty: seq <‘T> → bool | Проверяет, есть ли в последовательности какие-либо элементы. |
iter: (‘T → единица измерения) → seq <‘ T> → единица измерения | Применяет данную функцию к каждому элементу коллекции. |
iter2: (‘T1 →’ T2 → unit) → seq <‘T1> → seq <‘ T2> → unit | Применяет данную функцию одновременно к двум коллекциям. Если одна последовательность короче другой, то остальные элементы более длинной последовательности игнорируются. |
iteri: (int → ‘T → unit) → seq <‘ T> → unit | Применяет данную функцию к каждому элементу коллекции. Целое число, переданное функции, указывает на индекс элемента. |
последний: seq <‘T> →’ T | Возвращает последний элемент последовательности. |
длина: seq <‘T> → int | Возвращает длину последовательности. |
карта: (‘T →’ U) → seq <‘T> → seq <‘ U> | Создает новую коллекцию, элементы которой являются результатами применения данной функции к каждому из элементов коллекции. Данная функция будет применена, поскольку элементы требуются с помощью метода MoveNext на счетчиках, извлеченных из объекта. |
map2: (‘T1 →’ T2 → ‘U) → seq <‘ T1> → seq <‘T2> → seq <‘ U> | Создает новую коллекцию, элементы которой являются результатами применения данной функции к соответствующим парам элементов из двух последовательностей. Если одна входная последовательность короче другой, то остальные элементы более длинной последовательности игнорируются. |
mapi: (int → ‘T →’ U) → seq <‘T> → seq <‘ U> | Создает новую коллекцию, элементы которой являются результатами применения данной функции к каждому из элементов коллекции. Целочисленный индекс, переданный функции, указывает индекс (от 0) преобразовываемого элемента. |
max: seq <‘T> →’ T | Возвращает наибольший из всех элементов последовательности, сравниваемых с помощью Operators.max. |
maxBy: (‘T →’ U) → seq <‘T> →’ T | Возвращает наибольший из всех элементов последовательности по сравнению с использованием Operators.max для результата функции. |
min: seq <‘T> →’ T | Возвращает самый низкий из всех элементов последовательности по сравнению с использованием Operators.min. |
minBy: (‘T →’ U) → seq <‘T> →’ T | Возвращает самый низкий из всех элементов последовательности по сравнению с использованием Operators.min для результата функции. |
nth: int → seq <‘T> →’ T | Вычисляет n-й элемент в коллекции. |
ofArray: ‘T array → seq <‘ T> | Рассматривает данный массив как последовательность. |
ofList: ‘T list → seq <‘ T> | Рассматривает данный список как последовательность. |
попарно: seq <‘T> → seq <‘ T * ‘T> | Возвращает последовательность каждого элемента во входной последовательности и его предшественника, за исключением первого элемента, который возвращается только как предшественник второго элемента. |
выберите: (опция ‘T →’ U) → seq <‘T> →’ U | Применяет данную функцию к последовательным элементам, возвращая первое значение, где функция возвращает значение Some . |
только для чтения: seq <‘T> → seq <‘ T> | Создает новый объект последовательности, который делегируется данному объекту последовательности. Это гарантирует, что исходная последовательность не может быть заново открыта и видоизменена при помощи приведения типа. Например, если задан массив, возвращаемая последовательность вернет элементы массива, но вы не можете преобразовать возвращенный объект последовательности в массив. |
уменьшить: (‘T →’ T → ‘T) → seq <‘ T> → ‘T | Применяет функцию к каждому элементу последовательности, пропуская аргумент аккумулятора через вычисления. Начните с применения функции к первым двум элементам. Затем введите этот результат в функцию вместе с третьим элементом и так далее. Верните окончательный результат. |
scan: (‘State →’ T → ‘State) →’ State → seq <‘T> → seq <‘ State> | Как и Seq.fold, но вычисляет по требованию и возвращает последовательность промежуточных и конечных результатов. |
синглтон: ‘T → seq <‘ T> | Возвращает последовательность, которая дает только один элемент. |
skip: int → seq <‘T> → seq <‘ T> | Возвращает последовательность, которая пропускает указанное количество элементов базовой последовательности, а затем возвращает остальные элементы последовательности. |
skipWhile: (‘T → bool) → seq <‘ T> → seq <‘T> | Возвращает последовательность, которая после итерации пропускает элементы базовой последовательности, в то время как заданный предикат возвращает true, а затем возвращает остальные элементы последовательности. |
сортировать: seq <‘T> → seq <‘ T> | Возвращает последовательность, упорядоченную по ключам. |
sortBy: (‘T →’ Key) → seq <‘T> → seq <‘ T> | Применяет функцию генерации ключа к каждому элементу последовательности и выдает последовательность, упорядоченную по ключам. Ключи сравниваются с использованием общего сравнения, реализованного Operators.compare. |
сумма: seq <^ T> → ^ T | Возвращает сумму элементов в последовательности. |
sumBy | Возвращает сумму результатов, сгенерированных путем применения функции к каждому элементу последовательности. |
take: int → seq <‘T> → seq <‘ T> | Возвращает первые элементы последовательности до указанного количества. |
takeWhile: (‘T → bool) → seq <‘ T> → seq <‘T> | Возвращает последовательность, которая при повторении возвращает элементы базовой последовательности, в то время как данный предикат возвращает true, а затем не возвращает никаких дополнительных элементов. |
toArray: seq <‘T> →’ T [] | Создает массив из данной коллекции. |
toList: seq <‘T> →’ T list | Создает список из данной коллекции. |
усечение: int → seq <‘T> → seq <‘ T> | Возвращает последовательность, которая при перечислении возвращает не более указанного числа элементов. |
опция tryFind: (‘T → bool) → seq <‘ T> → ‘T | Возвращает первый элемент, для которого данная функция возвращает true, или None, если такого элемента не существует. |
опция tryFindIndex: (‘T → bool) → seq <‘ T> → int | Возвращает индекс первого элемента в последовательности, который удовлетворяет данному предикату, или None, если такого элемента не существует. |
tryPick: (опция ‘T →’ U) → опция seq <‘T> →’ U | Применяет данную функцию к последовательным элементам, возвращая первое значение, где функция возвращает значение Some . |
развернуть: (‘State →’ T * ‘State option) →’ State → seq <‘T> | Возвращает последовательность, которая содержит элементы, сгенерированные данным вычислением. |
где: (‘T → bool) → seq <‘ T> → seq <‘T> | Возвращает новую коллекцию, содержащую только те элементы коллекции, для которых данный предикат возвращает true . Синоним для Seq.filter. |
windowed: int → seq <‘T> → seq <‘ T []> | Возвращает последовательность, которая дает скользящие окна, содержащие элементы, взятые из входной последовательности. Каждое окно возвращается в виде нового массива. |
zip: seq <‘T1> → seq <‘ T2> → seq <‘T1 *’ T2> | Объединяет две последовательности в список пар. Две последовательности не должны иметь одинаковую длину — когда одна последовательность исчерпана, любые оставшиеся элементы в другой последовательности игнорируются. |
zip3: seq <‘T1> → seq <‘ T2> → seq <‘T3> → seq <‘ T1 * ‘T2 *’ T3> | Объединяет три последовательности в список троек. Последовательности не должны иметь одинаковую длину — когда одна последовательность исчерпана, все остальные элементы в других последовательностях игнорируются. |
Следующие примеры демонстрируют использование некоторых из вышеуказанных функций —
Пример 1
Эта программа создает пустую последовательность и заполняет ее позже —
(* Creating sequences *) let emptySeq = Seq.empty let seq1 = Seq.singleton 20 printfn"The singleton sequence:" printfn "%A " seq1 printfn"The init sequence:" let seq2 = Seq.init 5 (fun n -> n * 3) Seq.iter (fun i -> printf "%d " i) seq2 printfn"" (* converting an array to sequence by using cast *) printfn"The array sequence 1:" let seq3 = [| 1 .. 10 |] :> seq<int> Seq.iter (fun i -> printf "%d " i) seq3 printfn"" (* converting an array to sequence by using Seq.ofArray *) printfn"The array sequence 2:" let seq4 = [| 2..2.. 20 |] |> Seq.ofArray Seq.iter (fun i -> printf "%d " i) seq4 printfn""
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
The singleton sequence: seq [20] The init sequence: 0 3 6 9 12 The array sequence 1: 1 2 3 4 5 6 7 8 9 10 The array sequence 2: 2 4 6 8 10 12 14 16 18 20
Пожалуйста, обратите внимание, что —
-
Метод Seq.empty создает пустую последовательность.
-
Метод Seq.singleton создает последовательность только из одного указанного элемента.
-
Метод Seq.init создает последовательность, для которой элементы создаются с использованием данной функции.
-
Методы Seq.ofArray и Seq.ofList <‘T> создают последовательности из массивов и списков.
-
Метод Seq.iter позволяет выполнять итерацию последовательности.
Метод Seq.empty создает пустую последовательность.
Метод Seq.singleton создает последовательность только из одного указанного элемента.
Метод Seq.init создает последовательность, для которой элементы создаются с использованием данной функции.
Методы Seq.ofArray и Seq.ofList <‘T> создают последовательности из массивов и списков.
Метод Seq.iter позволяет выполнять итерацию последовательности.
Пример 2
Метод Seq.unfold генерирует последовательность из вычислительной функции, которая принимает состояние и преобразует его для создания каждого последующего элемента в последовательности.
Следующая функция выдает первые 20 натуральных чисел —
let seq1 = Seq.unfold (fun state -> if (state > 20) then None else Some(state, state + 1)) 0 printfn "The sequence seq1 contains numbers from 0 to 20." for x in seq1 do printf "%d " x printfn" "
Когда вы компилируете и запускаете программу, она выдает следующий вывод:
The sequence seq1 contains numbers from 0 to 20. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Пример 3
Метод Seq.truncate создает последовательность из другой последовательности, но ограничивает последовательность указанным количеством элементов.
Метод Seq.take создает новую последовательность, которая содержит указанное количество элементов с начала последовательности.
let mySeq = seq { for i in 1 .. 10 -> 3*i } let truncatedSeq = Seq.truncate 5 mySeq let takeSeq = Seq.take 5 mySeq printfn"The original sequence" Seq.iter (fun i -> printf "%d " i) mySeq printfn"" printfn"The truncated sequence" Seq.iter (fun i -> printf "%d " i) truncatedSeq printfn"" printfn"The take sequence" Seq.iter (fun i -> printf "%d " i) takeSeq printfn""
Когда вы компилируете и запускаете программу, она выдает следующий вывод: