Midoliy |> F# - クエリ式
クエリ式
Midoliy|F#プログラミング
クエリ式の概要
クエリ演算子の概要
 |> contains
 |> distinct
 |> exists
 |> find
 |> all
 |> nth
 |> where
 |> select
 |> count
 |> head
 |> headOrDefault
 |> last
 |> lastOrDefault
 |> exactlyOne
 |> exactlyOneOrDefault
 |> minBy
 |> minByNullable
 |> maxBy
 |> maxByNullable
 |> sumBy
 |> sumByNullable
 |> averageBy
 |> averageByNullable
 |> groupBy
 |> sortBy
 |> sortByDescending
 |> sortByNullable
 |> sortByNullableDescending
 |> skip

クエリ式の概要


 クエリ式(= query式)はF#でLINQをサポートするために存在しているコンピュテーション式です。
 LINQというのは、SQLのような文法でデータの集合を操作するための機能のことです。C#では非常によく使われる機能の一つです。それをF#でも利用できるようにしたのが、このクエリ式というわけです。

 クエリ式は、主にデータベースの操作によく使われますが、list型やarray型に使用しても問題ありません。ただし、list型などは、それぞれに特化したListモジュールやArrayモジュールを利用するのが一般的ですので、状況に合わせて使い分けできるとよいでしょう。

// [ 構文 ]
query { expression }

 構文の「expression」には、クエリ式内で有効なクエリ演算子などを利用した式が記述されます。
 以下は、select演算子を用いた、クエリ式の簡単な例です。



クエリ演算子の概要


 クエリ演算子を利用すると、データの集合から「ある条件」に合致するデータのみを取得したり、取得したデータ群をソートしたりするなどの処理を、SQLのように簡単に記述することが可能となります。ただし、対象のデータ集合がクエリ演算子をサポートしている必要があります。サポートされていないクエリ演算子を使用すると、System.NotSupportedExceptionがthrowされます。
 クエリ式にはSQL式に変換できる式のみ使用することが可能です。たとえば、whereクエリ演算子を使用する場合には、式の中で関数呼び出しをすることはできません。このように、各クエリ演算子によって許容されているコードが違いますので、注意しましょう。
 以下にクエリ演算子の一部を紹介いたします。ここで紹介するものがすべてではありませんので、その点ご留意ください。(今後すべての演算子を紹介できるよう、時々アップデートしていきます)


contains


 containsクエリ演算子は、選択した要素に指定の要素が含まれるかどうかを確認します。指定した要素が含まれる場合に、trueを返します。
// -------------------------------
// contains クエリ演算子のサンプル

// 0 ~ 9のlist
let ls = [0..9]

query {
    for i in ls do
        contains 5
}
|> printfn "contains 5= %b"
// output:
//      contains 5= true

query {
    for i in ls do
        contains 10
}
|> printfn "contains 10= %b"
// output:
//      contains 10= false


distinct


 distinctクエリ演算子は、選択した要素から重複なしのシーケンスを作成します。
// -------------------------------
// distinct クエリ演算子のサンプル

// 重複のあるリスト
let ls = [ 0; 0; 1; 2; 3; 3; 4; 5; 5; 5; 5; ]

query {
    for i in ls do
        distinct       // 重複なしのSeqを作成します.
}
|> Seq.toArray
|> printfn "distinct= %A"
// output:
//      distinct= [|0; 1; 2; 3; 4; 5|]

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        distinct        // 重複なしのSeqを作成します.
}
|> Seq.toArray
|> printfn "distinct= %A"
// output:
//      distinct= [|5|]


exists


 existsクエリ演算子は、選択した要素に特定の要素が存在しているかチェックします。条件に合致する特定の要素が存在している場合に、true を返します。
// -------------------------------
// exists クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        exists (i < 0)       // ls の中に 0未満の数値 が存在しているかチェックします.
}
|> printfn "exists (i < 0)= %b"
// output:
//      exists (i < 0)= false

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        exists (i = 7)  // whereで抽出した数値の中に 7 が存在しているかチェックします.
}
|> printfn "exists (i = 7)= %b"
// output:
//      exists (i = 7)= true


find


 findクエリ演算子は、指定された条件を満たす値を検索し、 条件を満たす最初の要素を取得してきます.
// -------------------------------
// find クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        find (2 <= i)       // lsの中から 2以上の値 を検索し, 条件を満たす先頭の要素を取得します.
}
|> printfn "find (2 <= i)= %d"
// output:
//      find (2 <= i)= 2

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        find (i = 7)    // whereで抽出した数値の中から 7 を検索します.
}
|> printfn "find (i = 7)= %d"
// output:
//      find (i = 7)= 7

// 条件に合致する値がない場合, System.InvalidOperationException が throw されます.
query {
    for i in ls do
        find (i < 0)
}
|> printfn "find (i < 0)= %d"
// output:
//      ハンドルされていない例外: System.InvalidOperationException:
//      シーケンスに、一致する要素は含まれてません


all


 allクエリ演算子は、これまでに抽出した値のすべての要素が条件を満たすかどうかをチェックします。 すべての要素が条件を満たす場合、true を返します。
// -------------------------------
// all クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        all (2 <= i)       // すべての要素が 2以上 かチェックします.
}
|> printfn "all (2 <= i)= %b"
// output:
//      all (2 <= i)= false

query {
    for i in ls do
        where (5 <= i)              // 5以上の値を抽出します.
        all (5 <= i && i < 10)      // 現在選択中の要素が 5以上, 10未満 かチェックします.
}
|> printfn "all (5 <= i && i < 10)= %b"
// output:
//      all (5 <= i && i < 10)= true


nth


 nthクエリ演算子は、これまでに抽出した値の中から、指定したインデックスにある要素を取得します。
// -------------------------------
// nth クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        nth 5       // lsの中から, 指定したインデックスにある要素を取得します.
}
|> printfn "nth 5= %d"
// output:
//      nth 5= 5

query {
    for i in ls do
        where (5 <= i)  // 5以上 の値を抽出します.
        nth 2           // 現在選択中の要素の中から, 指定したインデックスにある要素を取得します.
}
|> printfn "nth 2= %d"
// output:
//      nth 2= 7

// 選択している要素がない場合, System.ArgumentOutOfRangeException が throw されます.
query {
    for i in ls do
        where (i < 0)   // 0未満 の値を抽出します.
        nth 2
}
|> printfn "nth 2= %d"
// output:
//      ハンドルされていない例外: System.ArgumentOutOfRangeException: 
//      指定された引数は、有効な値の範囲内にありません。


where


 whereクエリ演算子は、指定した条件に基づいて要素を抽出します。
// -------------------------------
// where クエリ演算子のサンプル

// 0~9のlist
let ls = [0..9]

query {
    for i in ls do
        where (i < 5)   // listの中から [5未満の値] を抽出します.
}
|> Seq.toArray
|> printfn "where (i < 5)= %A"
// output:
//      where (i < 5)= [|0; 1; 2; 3; 4|]

query {
    for i in ls do
        where (i = 5)   // listの中から [5] と一致する値だけを抽出します.
}
|> Seq.toArray
|> printfn "where (i = 5)= %A"
// output:
//      where (i = 5)= [|5|]

query {
    for i in ls do
        where (10 < i)   // listの中から [10超過の値] を抽出します.
}
|> Seq.toArray
|> printfn "where (10 < i)= %A"
// output:
//      where (10 < i)= [||]


select


 selectクエリ演算子は、これまでに抽出した値の中にある必要な要素値を抽出することができます。
// -------------------------------
// select クエリ演算子のサンプル

[<Measure>]
type years

// サンプル用のrecord型
type Personal = { Name:string; Age:int<years>; }

let persons = [ 
    { Name="Alice"; Age=20<years>; }
    { Name="Bob"; Age=21<years>; }
    { Name="Cheryl"; Age=22<years>; }
    { Name="Daniel"; Age=23<years>; }
    { Name="Edward"; Age=24<years>; }
    { Name="Fernando"; Age=25<years>; }
]

query {
    for p in persons do
        select p.Name  // Pesonal listの各要素の中から, Name要素のみを抽出します.
}
|> Seq.toArray
|> printfn "select p.Name array= %A"
// output:
//      select p.Name array= [|"Alice"; "Bob"; "Cheryl"; "Daniel"; "Edward"; "Fernando"|]

query {
    for p in persons do
        select p.Age  // Pesonal listの各要素の中から, Age要素のみを抽出します.
}
|> Seq.toArray
|> printfn "select p.Age array= %A"
// output:
//      select p.Age array= [|20; 21; 22; 23; 24; 25|]

query {
    for p in persons do
        where (23<years> < p.Age)    // 年齢が23歳よりも上の人物のみ抽出します
        select p.Name         // whereで抽出した人物の名前のみ抽出します
}
|> Seq.toArray
|> printfn "array= %A"
// output:
//      array= [|"Edward"; "Fernando"|]


count


 countクエリ演算子は、これまでに抽出した要素数を取得します。
// -------------------------------
// count クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        count       // countだけ利用すると, 全要素数を取得可能です.
}
|> printfn "count= %d"
// output:
//      count= 10

query {
    for i in ls do
        where (i < 5)   // 5未満の値を抽出します.
        count           // whereで抽出した値の要素数を取得します.
}
|> printfn "count= %d"
// output:
//      count= 5


head


 headクエリ演算子は、これまでに抽出した要素の中から先頭の要素を取得します。
// -------------------------------
// head クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        head       // 全要素の中から先頭の要素を取得可能です.
}
|> printfn "head= %d"
// output:
//      head= 0

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        head            // whereで抽出した要素の先頭を取得します.
}
|> printfn "head= %d"
// output:
//      head= 5

query {
    for i in ls do
        where (10 < i)  // 10超過の値を抽出します.
        head            // 要素がない場合, 例外が発生します.
}
|> printfn "head= %d"
// output:
//      System.InvalidOperationException: シーケンスに要素が含まれていません.


headOrDefault


 headOrDefaultクエリ演算子は、これまでに抽出した要素の中から先頭の要素を取得します。また、シーケンスに要素がない場合は、デフォルト値を返します。
// ------------------------------------
// headOrDefault クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        headOrDefault   // 全要素の中から先頭の要素を取得可能です.
}
|> printfn "head= %d"
// output:
//      head= 0

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        headOrDefault   // whereで抽出した要素の先頭を取得します.
}
|> printfn "head= %d"
// output:
//      head= 5

query {
    for i in ls do
        where (10 < i)  // 10超過の値を抽出します.
        headOrDefault   // 要素がない場合, デフォルト値が得られます.
}
|> printfn "head= %d"
// output:
//      head= 0


last


 lastクエリ演算子は、これまでに抽出した要素の中から最後の要素を取得します。
// -------------------------------
// last クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        last       // 全要素の最後の要素を取得可能です.
}
|> printfn "last= %d"
// output:
//      last= 9

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        last            // whereで抽出した要素の最終要素を取得します.
}
|> printfn "last= %d"
// output:
//      last= 9

query {
    for i in ls do
        where (10 < i)  // 10超過の値を抽出します.
        last            // 要素がない場合, 例外が発生します.
}
|> printfn "last= %d"
// output:
//      System.InvalidOperationException: シーケンスに要素が含まれていません.


lastOrDefault


 lastOrDefaultクエリ演算子は、これまでに抽出した要素の中から最後の要素を取得します。また、シーケンスに要素がない場合は、デフォルト値を返します。
// -------------------------------
// lastOrDefault クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        lastOrDefault   // 全要素の最後の要素を取得可能です.
}
|> printfn "lastOrDefault= %d"
// output:
//      last= 9

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出します.
        lastOrDefault   // whereで抽出した要素の最終要素を取得します.
}
|> printfn "lastOrDefault= %d"
// output:
//      last= 9

query {
    for i in ls do
        where (10 < i)  // 10超過の値を抽出します.
        lastOrDefault   // 要素がない場合, デフォルト値が得られます.
}
|> printfn "lastOrDefault= %d"
// output:
//      lastOrDefault= 0


exactlyOne


 exactlyOneクエリ演算子は、選択されている要素が単一の場合にその要素を取得します。選択されている要素が複数存在するか、まったく存在しない場合には例外をthrowします。
// -------------------------------
// exactlyOne クエリ演算子のサンプル

[<Measure>] type old
type Person = { Name: string; Age: int<old>; }

let ls = [ { Name="alex"; Age=20<old>; }
           { Name="bob"; Age=21<old>; }
           { Name="carol"; Age=22<old>; }
           { Name="daniel"; Age=23<old>; } ]

query {
    for p in ls do
        where (p.Age = 21<old>)   // 21歳のPersonのみ抽出.
        exactlyOne                // 現在選択している要素が一つのみの場合に, 値を返します.
}
|> printfn "exactlyOne= %A"
// output:
//      exactlyOne= {Name = "bob"; Age = 21;}

query {
    for p in ls do
        where (p.Age < 20<old>)    // 20歳未満のPersonを抽出
        exactlyOne                 // 現在選択している要素が一つもない場合, 例外が発生します.
}
|> printfn "exactlyOne= %A"
// output:
//      ハンドルされていない例外: System.InvalidOperationException:
//      シーケンスに要素が含まれていません

query {
    for i in ls do
        exactlyOne              // 要素が複数ある場合, 例外が発生します.
}
|> printfn "exactlyOne= %A"
// output:
//      ハンドルされていない例外: System.InvalidOperationException: 
//      シーケンスに複数の要素が含まれています


exactlyOneOrDefault


 exactlyOneクエリ演算子は、選択されている要素が単一の場合にその要素を取得します。選択している要素がまったく存在しない場合にはデフォルト値を返し、選択されている要素が複数存在する場合には例外をthrowします。
// ------------------------------------------
// exactlyOneOrDefault クエリ演算子のサンプル

[<Measure>] type old
type Person = { Name: string; Age: int<old>; }

let ls = [ { Name="alex"; Age=20<old>; }
           { Name="bob"; Age=21<old>; }
           { Name="carol"; Age=22<old>; }
           { Name="daniel"; Age=23<old>; } ]

query {
    for p in ls do
        where (p.Age = 21<old>)     // 21歳のPersonのみ抽出.
        exactlyOneOrDefault         // 現在選択している要素が一つのみの場合に, 値を返します.
}
|> printfn "exactlyOneOrDefault= %A"
// output:
//      exactlyOne= {Name = "bob"; Age = 21;}

query {
    for p in ls do
        where (p.Age < 20<old>)     // 20歳未満のPersonを抽出
        exactlyOneOrDefault         // 現在選択している要素が一つもない場合, デフォルト値を返します.
}
|> printfn "exactlyOneOrDefault= %A"
// output:
//      exactlyOneOrDefault= <null>

query {
    for i in ls do
        exactlyOneOrDefault         // 要素が複数ある場合, 例外が発生します.
}
|> printfn "exactlyOneOrDefault= %A"
// output:
//      ハンドルされていない例外: System.InvalidOperationException: 
//      シーケンスに複数の要素が含まれています


minBy


 minByクエリ演算子は、選択されている要素の中から最小の値を取得します。
// -------------------------------------
// minBy クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        minBy i
}
|> printfn "minBy= %d"
// output:
//      minBy= 0

query {
    for i in ls do
        where (5 <= i)   // 5以上の値を抽出
        minBy i
}
|> printfn "minBy= %d"
// output:
//      minBy= 5

query {
    for i in ls do
        where (i < 0)   // 0未満の値を抽出
        minBy i         // 現在選択している要素が一つもない場合, 例外が発生します.
}
|> printfn "minBy= %d"
// output:
//      ハンドルされていない例外: System.InvalidOperationException:
//      シーケンスに要素が含まれていません


minByNullable


 minByNullableクエリ演算子は、Null許容型の要素に対して利用することができ、選択されている要素の中から最小の値を取得します。その際nullは無視されます。
// -------------------------------------
// minByNullable クエリ演算子のサンプル
open System

let ls = [ Nullable(1)
           Nullable()
           Nullable(2)
           Nullable(4)
           Nullable()
           Nullable(9)
           Nullable(12) ]

query {
    for i in ls do
        minByNullable i
}
|> printfn "minByNullable= %A"
// output:
//      minByNullable= 1

query {
    for i in ls do
        where (if i.HasValue then 3 <= i.Value else false)   // 3以上の値を抽出
        minByNullable i
}
|> printfn "minByNullable= %A"
// output:
//      minByNullable= 4

query {
    for i in ls do
        where (if i.HasValue then i.Value < 0 else false)   // 0未満の値を抽出
        minByNullable i
}
|> printfn "minByNullable= %A"
// output:
//      minByNullable= <null>


maxBy


 maxByクエリ演算子は、選択されている要素の中から最大の値を取得します。
// -------------------------------------
// maxBy クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do
        maxBy i         // 最大値を取得
}
|> printfn "maxBy= %A"
// output:
//      maxBy= 9

query {
    for i in ls do
        where (3 <= i && i < 8)   // 3以上 かつ 8未満 の値を抽出
        maxBy i                   // 現在抽出している要素の中で最大の値を取得
}
|> printfn "maxBy= %A"
// output:
//      maxBy= 7

query {
    for i in ls do
        where (i < 0)       // 0未満の値を抽出
        maxBy i             // 要素数が0の場合は, 例外が発生します
}
|> printfn "maxBy= %A"
// output:
//      ハンドルされていない例外: System.InvalidOperationException:
//      シーケンスに要素が含まれていません


maxByNullable


 maxByNullableクエリ演算子は、Null許容型の要素に対して利用することができ、選択されている要素の中から最大の値を取得します。その際nullは無視されます。

// -------------------------------------
// maxByNullable クエリ演算子のサンプル
open System

let ls = [ Nullable(1)
           Nullable()
           Nullable(2)
           Nullable(4)
           Nullable()
           Nullable(9)
           Nullable(12) ]

query {
    for i in ls do
        maxByNullable i
}
|> printfn "maxByNullable= %A"
// output:
//      maxByNullable= 12

query {
    for i in ls do
        where (if i.HasValue then i.Value < 10  else false)   // 10未満の値を抽出
        maxByNullable i
}
|> printfn "maxByNullable= %A"
// output:
//      maxByNullable= 9

query {
    for i in ls do
        where (if i.HasValue then i.Value < 0 else false)   // 0未満の値を抽出
        maxByNullable i
}
|> printfn "maxByNullable= %A"
// output:
//      maxByNullable= <null>


sumBy


 sumByクエリ演算子は、選択されている要素の合計値を取得します。
// -------------------------------------
// sumBy クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do 
        sumBy i
}
|> printfn "sumBy= %d"
// output:
//      sumBy= 45

query {
    for i in ls do
        where (5 <= i)  // 5以上の値を抽出
        sumBy i         // 抽出した値を合計
}
|> printfn "sumBy= %d"
// output:
//      sumBy= 35

query {
    for i in ls do
        where (i < 0)   // 0未満の値を抽出
        sumBy i         // 対象要素が0の場合, 0を返します
}
|> printfn "sumBy= %d"
// output:
//      sumBy= 0


sumByNullable


 sumByNullableクエリ演算子は、Null許容型の要素に対して利用することができ、選択されている要素の合計値を取得します。その際nullは無視されます。
// -------------------------------------
// sumByNullable クエリ演算子のサンプル
open System

let ls = [ Nullable(1)
           Nullable()
           Nullable(2)
           Nullable(4)
           Nullable()
           Nullable(9)
           Nullable(12) ]

query {
    for i in ls do
        sumByNullable i
}
|> printfn "sumByNullable= %A"
// output:
//      sumByNullable= 28

query {
    for i in ls do
        where (if i.HasValue then i.Value < 10  else false)   // 10未満の値を抽出
        sumByNullable i
}
|> printfn "sumByNullable= %A"
// output:
//      sumByNullable= 16

query {
    for i in ls do
        where (if i.HasValue then i.Value < 0 else false)   // 0未満の値を抽出
        sumByNullable i
}
|> printfn "sumByNullable= %A"
// output:
//      sumByNullable= 0


averageBy


 averageByクエリ演算子は、選択されている要素の平均値を取得します。
// -------------------------------------
// averageBy クエリ演算子のサンプル

let ls = [ 0..9 ]

query {
    for i in ls do 
        averageBy (float i)
}
|> printfn "averageBy= %f"
// output:
//      averageBy= 4.500000

query {
    for i in ls do
        where (5 <= i)          // 5以上の値を抽出
        averageBy (float i)     // 抽出した値を合計
}
|> printfn "averageBy= %f"
// output:
//      averageBy= 7.000000

query {
    for i in ls do
        where (i < 0)           // 0未満の値を抽出
        averageBy (float i)     // 対象要素が0の場合, 例外が発生します
}
|> printfn "averageBy= %f"
// output:
//      ハンドルされていない例外: System.InvalidOperationException: source


averageByNullable


 averageByNullableクエリ演算子は、Null許容型の要素に対して利用することができ、選択されている要素の平均値を取得します。その際nullは無視されます。
// -------------------------------------
// averageByNullable クエリ演算子のサンプル
open System

let ls = [ Nullable(1.)
           Nullable()
           Nullable(2.)
           Nullable(4.)
           Nullable()
           Nullable(9.)
           Nullable(12.) ]

query {
    for i in ls do
        averageByNullable i
}
|> printfn "averageByNullable= %A"
// output:
//      averageByNullable= 4.0

query {
    for i in ls do
        where (if i.HasValue then i.Value < 10.  else false)   // 10未満の値を抽出
        averageByNullable i
}
|> printfn "averageByNullable= %A"
// output:
//      averageByNullable= 4.0

query {
    for i in ls do
        where (if i.HasValue then i.Value < 0. else false)   // 0未満の値を抽出
        averageByNullable i
}
|> printfn "averageByNullable= %A"
// output:
//      averageByNullable= 


groupBy


 groupByクエリ演算子は、選択されている要素を、指定したキーセレクターに従ってグループ化します。
// -------------------------------------
// groupBy クエリ演算子のサンプル

type Person = { ID: string; Name: string; Age: int; }

let persons = [ { ID="0x00"; Name="Alice";  Age=22}
                { ID="0x00"; Name="Bob";    Age=23}
                { ID="0x01"; Name="Chris";  Age=32}
                { ID="0x01"; Name="Edward"; Age=45}
                { ID="0x02"; Name="Felix";  Age=26} ]

query {
    for p in persons do 
        groupBy p.ID into g     // Person.IDでグループ化
        select g
}
|> printfn "groupBy= %A"
// output:  ID毎にグループ化されていることがわかります.
//      groupBy= [seq [{ID = "0x00";
//                      Name = "Alice";
//                      Age = 22;};
//                     {ID = "0x00";
//                      Name = "Bob";
//                      Age = 23;}]; 
//                seq [{ID = "0x01";
//                      Name = "Chris";
//                      Age = 32;};
//                     {ID = "0x01";
//                      Name = "Edward";
//                      Age = 45;}];
//                seq [{ID = "0x02";
//                      Name = "Felix";
//                      Age = 26;}]]

query {
    for p in persons do
        groupBy p.ID into g     // Person.IDでグループ化
        select g.Key            // Keyとなった値のみを抽出
}
|> printfn "groupBy= %A"
// output:  Key値が重複なしで取得可能です.
//      groupBy= seq ["0x00"; "0x01"; "0x02"]


sortBy


 sortByクエリ演算子は、選択されている要素を、昇り順にソートしたシーケンスを取得します。
// -------------------------------------
// sortBy クエリ演算子のサンプル

let ls = [ 5; 9; 6; 3; 2; 0; 4; 1; 7; 8; ]

query {
    for l in ls do
        sortBy l    // 昇り順にソート
}
|> Seq.toList
|> printfn "sortBy= %A"
// output:
//      sortBy= [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]

// 元のリストには影響がないことが確認できます.
ls |> printfn "sortBy= %A"
// output:
//      sortBy= [5; 9; 6; 3; 2; 0; 4; 1; 7; 8]

query {
    for l in ls do
        where (l < 6)   // 6未満の値を抽出
        sortBy l        // 昇り順にソート
}
|> Seq.toList
|> printfn "sortBy= %A"
// output:
//      sortBy= [0; 1; 2; 3; 4; 5]

query {
    for l in ls do
        where (l < 0)   // 0未満の値を抽出
        sortBy l
}
|> Seq.toList
|> printfn "sortBy= %A"
// output:
//      sortBy= []


sortByDescending


 sortByDescendingクエリ演算子は、選択されている要素を、降り順にソートしたシーケンスを取得します。
// -------------------------------------
// sortByDescending クエリ演算子のサンプル

let ls = [ 5; 9; 6; 3; 2; 0; 4; 1; 7; 8; ]

query {
    for l in ls do
        sortByDescending l    // 降り順にソート
}
|> Seq.toList
|> printfn "sortByDescending= %A"
// output:
//      sortByDescending= [9; 8; 7; 6; 5; 4; 3; 2; 1; 0]

// 元のリストには影響がないことが確認できます.
ls |> printfn "sortByDescending= %A"
// output:
//      sortByDescending= [5; 9; 6; 3; 2; 0; 4; 1; 7; 8]

query {
    for l in ls do
        where (l < 6)           // 6未満の値を抽出
        sortByDescending l      // 降り順にソート
}
|> Seq.toList
|> printfn "sortByDescending= %A"
// output:
//      sortByDescending= [5; 4; 3; 2; 1; 0]

query {
    for l in ls do
        where (l < 0)           // 0未満の値を抽出
        sortByDescending l
}
|> Seq.toList
|> printfn "sortByDescending= %A"
// output:
//      sortByDescending= []


sortByNullable


 sortByNullableクエリ演算子は、選択されているnull許容の要素を、昇り順にソートしたシーケンスを取得します。その際nullは無視されません。
// -------------------------------------
// sortByNullable クエリ演算子のサンプル
open System

let ls = [ Nullable(10.)
           Nullable()
           Nullable(0.)
           Nullable(6.)
           Nullable(4.)
           Nullable()
           Nullable(1.)
           Nullable(12.) ]

query {
    for i in ls do
        sortByNullable i
}
|> Seq.toList
|> printfn "sortByNullable= %A"
// output:
//      sortByNullable= [null; null; 0.0; 1.0; 4.0; 6.0; 10.0; 12.0]

query {
    for i in ls do
        where (if i.HasValue then i.Value < 10.  else false)   // 10未満の値を抽出
        sortByNullable i
}
|> Seq.toList
|> printfn "sortByNullable= %A"
// output:
//      sortByNullable= [0.0; 1.0; 4.0; 6.0]

query {
    for i in ls do
        where (if i.HasValue then i.Value < 0. else false)   // 0未満の値を抽出
        sortByNullable i
}
|> Seq.toList
|> printfn "sortByNullable= %A"
// output:
//      sortByNullable= []


sortByNullableDescending


 sortByNullableDescendingクエリ演算子は、選択されているnull許容の要素を、降り順にソートしたシーケンスを取得します。その際nullは無視されません。
// -------------------------------------
// sortByNullableDescending クエリ演算子のサンプル
open System

let ls = [ Nullable(10.)
           Nullable()
           Nullable(0.)
           Nullable(6.)
           Nullable(4.)
           Nullable()
           Nullable(1.)
           Nullable(12.) ]

query {
    for i in ls do
        sortByNullableDescending i
}
|> Seq.toList
|> printfn "sortByNullableDescending= %A"
// output:
//      sortByNullableDescending= [12.0; 10.0; 6.0; 4.0; 1.0; 0.0; null; null]

query {
    for i in ls do
        where (if i.HasValue then i.Value < 10.  else false)   // 10未満の値を抽出
        sortByNullableDescending i
}
|> Seq.toList
|> printfn "sortByNullableDescending= %A"
// output:
//      sortByNullableDescending= [6.0; 4.0; 1.0; 0.0]

query {
    for i in ls do
        where (if i.HasValue then i.Value < 0. else false)   // 0未満の値を抽出
        sortByNullableDescending i
}
|> Seq.toList
|> printfn "sortByNullableDescending= %A"
// output:
//      sortByNullableDescending= []


skip


 skipクエリ演算子は、選択されている要素の先頭要素から指定した数分スキップしたシーケンスを取得します。
// -------------------------------------
// skip クエリ演算子のサンプル

let ls = [ 5; 9; 6; 3; 2; 0; 4; 1; 7; 8; ]

query {
    for l in ls do
        skip 3    // 先頭要素から3要素分スキップ
}
|> Seq.toList
|> printfn "skip 3= %A"
// output:
//      skip 3= [3; 2; 0; 4; 1; 7; 8]

query {
    for l in ls do
        sortBy l    // 昇順にソート
        skip 5      // 先頭要素から5要素分スキップ
}
|> Seq.toList
|> printfn "sortBy l >> skip 5= %A"
// output:
//      sortBy l >> skip 5= [5; 6; 7; 8; 9]

query {
    for l in ls do
        where (l < 0)  // 0未満の値を抽出
        skip 3         // 対象要素が0の場合でも, 例外は発生しない
}
|> Seq.toList
|> printfn "where (l < 0) >> skip 3= %A"
// output:
//      where (l < 0) >> skip 3= []