Учебники

F # — последовательности

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

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

Последовательности определяются с использованием следующего синтаксиса —

seq { expr }

Например,

let seq1 = seq { 1 .. 10 }

Создание последовательностей и выражений последовательностей

Подобно спискам, вы можете создавать последовательности, используя диапазоны и значения.

Выражения последовательностей — это выражения, которые вы можете написать для создания последовательностей. Это может быть сделано —

  • Указав диапазон.
  • Указав диапазон с приращением или уменьшением.
  • Используя ключевое слово yield для получения значений, которые становятся частью последовательности.
  • С помощью оператора →.

Следующие примеры демонстрируют концепцию —

Пример 1

Live Demo

(* 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 —

Live Demo

(* 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

Эта программа создает пустую последовательность и заполняет ее позже —

Live Demo

(* 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 натуральных чисел —

Live Demo

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 создает новую последовательность, которая содержит указанное количество элементов с начала последовательности.

Live Demo

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""

Когда вы компилируете и запускаете программу, она выдает следующий вывод: