4

leftOuterJoin MSDNの Query Expressions のドキュメントは、サンプルを通じて、それを使用する場合でも、目的の効果を得るために leftOuterJoin .. on .. into ..使用する必要があることを繰り返し暗示しています。.DefaultIfEmpty()

これらのテストの両方で同じ結果が得られるため、これが必要だとは思わない..DefaultIfEpmty()

type Test = A | B | C
let G = [| A; B; C|]
let H = [| A; C; C|]

printfn "%A" <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I.DefaultIfEmpty() do 
    select (g, i)}

printfn "%A" <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I do 
    select (g, i)}

// seq [(A, A); (B, null); (C, C); (C, C)]
// seq [(A, A); (B, null); (C, C); (C, C)]

1) これを確認できますか?

そうである場合、比類のない結果をより適切に処理するために、この代替型拡張を作成した後に初めてそれに気付きましたnull。出力にまだ s が表示されていることに驚きました!

type IEnumerable<'TSource> with
    member this.NoneIfEmpty = if (Seq.exists (fun _ -> true) this) 
                              then Seq.map (fun e -> Some e) this 
                              else seq [ None ]

printfn "%A" <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I.NoneIfEmpty do 
    select (g, i)}

// seq [(A, Some A); (B, Some null); (C, Some C); (C, Some C)]

2)Noneの代わりにnull/Some nullを取得する方法はありleftOuterJoinますか?

3) 私が本当にやりたいことは、比類のないものがあるかどうかを調べることですg

printfn "%A" <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I.NoneIfEmpty do
    where (i.IsNone)
    exists (true) }

私はこの次のものを考え出しましたが、それはあまりF#ではありません:

printfn "%A" <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I do
    where (box i = null) 
    exists (true)}
4

1 に答える 1

4

短いバージョン: クエリ式は null を使用します。それは言語の大まかな場所ですが、封じ込め可能なものです.

私は前にこれをやった:

let ToOption (a:'a) =
    match obj.ReferenceEquals(a,null) with
    | true -> None
    | false -> Some(a)

これにより、次のことが可能になります。

printfn "%A" <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I do 
    select ( g,(ToOption i))}

これは、すべての結果をオプションでラップします (I が存在するかどうかわからないためです。F# はnull最適化として実行時に None を表すために使用することに注意してください。したがって、これが実際に必要なものであるかどうかを確認するには、次のようにオプションを決定します。

Seq.iter (fun (g,h) -> 
              printf "%A," g; 
              match h with 
              | Some(h) -> printfn "Some (%A)" h 
              | None -> printfn "None")  
    <| query {
    for g in G do
    leftOuterJoin h in H on (g = h) into I
    for i in I do 
    select ((ToOption g),(ToOption i))}
于 2014-09-24T04:55:02.723 に答える