F# - 像List.find一样的函数但是搜索任何一个Dictionary的键

时间:2013-12-02 18:38:32

标签: f#

我想创建一个像List.find这样的F#函数,但是我想搜索字典中的任何键并返回相应的字典值,而不是搜索单个值。 例如,这是我正在尝试做的(差)实现。

let dict1=dict[(1,"A");(2,"B");(3,"C");(4,"D");(5,"E");(6,"F")]

let findInDict l = 
    let mutable found=false
    let mutable value=""
    for elem in l do
        let f,v=dict1.TryGetValue(elem)
        value<-if f && not found then v else value
        found<-if not found then f else found
    value

findInDict [9;2;5]


> 

val dict1 : System.Collections.Generic.IDictionary<int,string>
val findInDict : l:seq<int> -> string
val it : string = "B"

什么是功能等同物?

3 个答案:

答案 0 :(得分:2)

这个功能几乎感觉有点矫枉过正。您可以使用列表解析在一行中执行此操作:

[for x in [9;4;5] do if dict1.ContainsKey x then yield dict1.[x]]

编辑:

重新阅读你的问题之后,我意识到上面的内容并不是你想要的。

let rec findAValue l =
    match l with
    | [] -> None
    | x::xs -> if dict1.ContainsKey x then Some(dict1.[x]) else findAValue xs

或更简洁:

let rec findAValue = function 
           | [] -> None
           | x::xs -> if dict1.ContainsKey x then Some(dict1.[x]) else findAValue xs

更简洁:

let findAValue = List.tryPick (fun x-> if dict1.ContainsKey x then Some(dict1.[x]) else None)

let highPerformanceFindAValue = List.tryPick (fun x-> match dict1.TryGetValue x with 
                                                      | true, value->Some(value) 
                                                      | _ -> None)

如果未找到任何值,则结果为None,否则为Some(value)

答案 1 :(得分:0)

let findFirst l (dict: System.Collections.Generic.Dictionary<int, string>) = 
    let o = l |> List.tryFind (fun i -> dict.ContainsKey(i)) |> Option.map (fun k -> dict.[k])
    match o with | None -> "" | Some(k) -> k

答案 2 :(得分:0)

有很多方法可以做到这一点。

显而易见的解决方案是迭代,就像你一样:

let findInDict (d:IDictionary<'a, 'b>) l =
    seq {
        for key in l do
            let f, v = d.TryGetValue(key)
            if f then yield v
    }

这是好的,我想。它或多或少地模仿了典型的逐步方法。

你可以用一些序列运算符重写这个:

let findInDict1 (d:IDictionary<'a, 'b>) l =
    Seq.filter (fun elem -> d.ContainsKey(elem)) l |> Seq.map (fun elem -> d.Item(elem))

感觉功能更强,但显然正在做更多的工作。

let findInDict2 (d:IDictionary<'a, 'b>) l =
    Seq.choose(fun elem ->
        let f,v = d.TryGetValue(elem)
        if f then Some(v) else None) l

最后一个是最有意义的,因为我们每个键只能访问一次字典,并且选择将为我们完成所有繁重的工作。