2017-03-15 141 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"