F# equivalent of LINQ Single

南楼画角 提交于 2019-11-29 16:13:15

In F# 2.0, this is a solution works without enumerating the whole sequence (close to your 2nd approach):

module Seq =
    let exactlyOne seq =
        match seq |> Seq.truncate 2 with
        | s when Seq.length s = 1 -> s |> Seq.head |> Some
        | _ -> None

    let single predicate =
        Seq.filter predicate >> exactlyOne

I choose to return option type since raising exception is quite unusual in F# high-order functions.

EDIT:

In F# 3.0, as @Oxinabox mentioned in his comment, Seq.exactlyOne exists in Seq module.

What about

let Single source f =
    let worked = ref false
    let newf = fun a -> 
        match f a with
        |true -> 
            if !worked = true then failwith "not single"
            worked := true
            Some(a)
        |false -> None
    let r = source |> Seq.choose newf
    Seq.nth 0 r 

Very unidiomatic but probably close to optimal

EDIT:

Solution with exactlyOne

let only2 f s= (Seq.filter f s) |> exactlyOne
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!