Saya mengonversi array ke tipe rekaman. Sesuatu seperti:

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

Ini berfungsi, tetapi memiliki kelemahan bahwa menambahkan nilai ke tengah array menghasilkan pengeditan manual dari semua referensi indeks setelahnya seperti ini:

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

Selain itu, mudah untuk secara tidak sengaja mendapatkan indeks yang salah.

Solusi yang saya buat adalah:

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 }

Ini berfungsi, tetapi saya sangat tidak menyukai sel referensi untuk sesuatu yang tidak bersamaan. Apakah ada cara yang lebih baik/bersih untuk mencapai ini?

f#
4
N_A 15 Maret 2017, 18:24

2 jawaban

Jawaban Terbaik

Anda bisa menggunakan pencocokan pola.

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"

Saat menambahkan entri lain ke larik, Anda akan menyesuaikannya dengan mengedit kecocokan pertama ke [|one; six; two; three; four; five|].

Omong-omong, untuk indeks yang bisa berubah seperti yang Anda gunakan dalam contoh Anda saat ini, Anda dapat menghindari ref dengan menggunakan kata kunci yang bisa berubah, seperti;

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

Dan jika kita menyembunyikan yang bisa berubah di dalam fungsi getIndex

let getIndex =
    let mutable index = -1
    fun () ->
        index <- index + 1
        index
5
hlo 15 Maret 2017, 15:54

Anda dapat membiarkan indeks ditangani dengan pencocokan pola, dan menambahkan pola aktif, seperti ini:

  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"
3
Isak 15 Maret 2017, 16:09