4

leftOuterJoin MSDN 上查询表达式的文档通过示例反复暗示,在使用时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 nullleftOuterJoin

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

短版:查询表达式使用空值。这是语言中的一个粗糙点,但可以控制。

我以前做过这个:

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 回答