2017-03-15 138 views
4

我将数组转换为记录类型。喜欢的东西:F ++等价的++运算符

let value = [|"1";"2";"3";"Not a number";"5"|] 
type ValueRecord = { 
    One: int32 
    Two: int32 
    Three: int32 
    Four: string 
    Five: int32 } 

let convertArrayToRecord (x: string array) = 
    { One = x.[0] |> Int.Parse 
    Two = x.[1] |> Int.Parse 
    Three = x.[2] |> Int.Parse 
    Four = x.[3] 
    Five = x.[4] |> Int.Parse } 

let recordValue = convertArrayToRecord value 

这工作,但具有以下缺点:增加值在所有索引引用的人工编辑的阵列结果的中间此后这样的:

let value = [|"1";"Not a number - 6";"2";"3";"Not a number";"5"|] 
type ValueRecord = { 
    One: int32 
    Six: string 
    Two: int32 
    Three: int32 
    Four: string 
    Five: int32 } 

let convertArrayToRecord (x: string array) = 
    { One = x.[0] |> Int.Parse 
    Six = x.[1] 
    Two = x.[2] |> Int.Parse //<--updated index 
    Three = x.[3] |> Int.Parse //<--updated index 
    Four = x.[4] //<--updated index 
    Five = x.[5] |> Int.Parse } //<--updated index 

let recordValue = convertArrayToRecord value 

此外,它很容易意外地使索引错误。

我想出了解决的办法是:

let convertArrayToRecord (x: string array) = 
    let index = ref 0 
    let getIndex() = 
     let result = !index 
     index := result + 1 
     result 
    { One = x.[getIndex()] |> Int.Parse 
     Six = x.[getIndex()] 
     Two = x.[getIndex()] |> Int.Parse 
     Three = x.[getIndex()] |> Int.Parse 
     Four = x.[getIndex()] 
     Five = x.[getIndex()] |> Int.Parse } 

这工作,但我真的不喜欢的东西,这是不是并发裁判细胞。有没有更好的/更清洁的方法来完成这个?

回答

5

您可以使用模式匹配。

let convertArrayToRecord = function 
    | [|one; two; three; four; five|] -> 
     { 
      One = int one 
      Two = int two 
      Three = int three 
      Four = four 
      Five = int five 
     } 
    | _ -> 
     failwith "How do you want to deal with arrays of a different length" 

当添加另一个入口到数组你会通过编辑第一场比赛到[|one; six; two; three; four; five|]调整。顺便说一下,对于你当前使用的可变索引,你可以使用mutable关键字来避免ref,就像这样;

let mutable index = -1 
let getIndex = 
    index <- index + 1 
    index 

如果我们隐藏了getIndex函数内部的可变

let getIndex = 
    let mutable index = -1 
    fun() -> 
     index <- index + 1 
     index 
+0

嗯,我很困惑。我想如果你关闭一个可变的它必须是一个参考单元格。 – mydogisbox

+2

通过模式匹配进行上传 - 如果更改数组的长度并且不更新模式,则会收到编译器警告,提醒您修复它。 –

+4

@mydogisbox从F#4.0开始,您可以使用mutable而不是ref(编译器会为您找到它,所以它仍然会放在堆上 - 与您在代码中使用ref相同)。请参阅https://blogs.msdn.microsoft.com/fsharpteam/2014/11/12/announcing-a-preview-of-f-4-0-and-the-visual-f-tools-in-vs-2015 /,简称使用可变值 – hlo

3

你可以让指数与模式匹配处理,并添加活动模式,像这样:

let (|PInt32|_|) (s:string) = 
    let ok, i = Int32.TryParse(s) 
    if ok then Some(PInt32(s)) else None 

    let foo() = 
    match [|"1"; "2"; "Some str"|] with 
    | [|PInt32(x); PInt32(y); mystr|] -> 
     printfn "Yup" 
    | _ -> printfn "Nope"