在F#中将字符串转换为键值对

时间:2016-07-06 22:33:50

标签: f#

给出一个字符串,如

  

一个:1.0 | 2:2.0 | 3:3.0

我们如何创建表单字符串的字典:float?

open System
open System.Collections.Generic

let ofSeq (src:seq<'a * 'b>) = 
    // from fssnip
    let d = new Dictionary<'a, 'b>()
    for (k,v) in src do
        d.Add(k,v)
    d


let msg = "one:1.0|two:2.0|three:3.0"
let msgseq = msg.Split[|'|'|] |> Array.toSeq |> Seq.map (fun i -> i.Split(':'))
let d = ofSeq msgseq // The type ''a * 'b' does not match the type 'string []'

此操作将在一个紧凑的循环中,因此效率将是一个加号。虽然我想看到一个简单的解决方案,只是为了获得我的F#轴承。

感谢。

2 个答案:

答案 0 :(得分:3)

这样的事情怎么样:

let msg = "one:1.0|two:2.0|three:3.0"

let splitKeyVal (str : string) =
    match str.Split(':') with
    |[|key; value|] ->  (key, System.Double.Parse(value))
    |_ -> invalidArg "str" "str must have the format key:value"

let createDictionary (str : string) =
    str.Split('|') 
    |> Array.map (splitKeyVal)
    |> dict
    |> System.Collections.Generic.Dictionary

如果您不介意System.Collections.Generic.Dictionary返回类型,则可以删除IDictionary

如果您希望splitKeyVal函数失败,那么您最好将其表达为返回选项的函数,例如:

let splitKeyVal (str : string) =
    match str.Split(':') with
    |[|key; valueStr|] ->  
        match System.Double.TryParse(valueStr) with
        |true, value -> Some (key, value)
        |false, _ -> None
    |_ -> None

但是你还必须决定如何处理createDictionary函数中的失败。

答案 1 :(得分:2)

不确定性能方面,但如果您确定自己的输入并且能够“承受”警告,您可以选择:

let d =
    msg.Split '|'
    |> Array.map (fun s -> let [|key; value|] (*warning here*) = s.Split ':' in key, value)
    |> dict
    |> System.Collections.Generic.Dictionary // optional if a IDictionary<string, string> suffice