2017-10-13 35 views
2

我有一個包含每天的重量如下csv文件:F# - 重量(計量單位),石磅

Date,Name,Weight 
11-Sep-2017,Alpha,9-1 
13-Sep-2017,Alpha,8-13 
15-Sep-2017,Alpha,8-11 

雖然我可以用CsvProvider,重量欄默認爲System.DateTime成功導入。

// Weight 
    [<Measure>] type lb 

    [<Literal>] 
    let input = "DayWeights.csv" 
    type Weights = CsvProvider<input, HasHeaders=true> 

    let data = Weights.GetSample() 
    for row in data.Rows do 
     printfn "Output: (%A, %A, %A)" row.Date row.Name row.Weight 

是否有可能建立措施(計量單位)的單位來界定「STLB」的選項轉換成進口磅,如果是這樣,怎麼樣?

+0

您不指定任何類型,所以類型提供者必須推斷該類型。爲什麼要使用* unknown *'lb'度量?順便說一句,爲什麼會有人類? '-'不用作任何數值的分隔符 –

+0

不幸的是,我無法控制csv文件的格式。 – matekus

+0

這不是文件。提供商無法通過查看數據來猜測您想要使用'lb'。你必須告訴它使用哪種類型 –

回答

2

我不認爲你可以將stone-pounds表示爲一個單一的數字類型,並且度量單位只能用於數字類型(儘管在將來有改變這種情況有some discussion)。這是因爲它們的一些功能只有在數字操作(如加法和乘法)中才有意義。自身相乘,分單位:

[<Measure>] type lb 
2<lb> + 2<lb> // 4<lb> 
2<lb> * 2<lb> // 4<lb^2> 
2<lb>/2<lb> // 1 

取而代之的度量單位,如果你想要某種標籤就知道給定值的類型爲石磅,你可以創建一個單一的情況下,判別聯合:

type StonesPounds = StonesPounds of int * int 

// StonesPounds -> int<lb> 
let convertToLb (StonesPounds (s, p)) = (s * 14 + p) * 1<lb> 

StonesPounds (1, 2) |> convertToLb // 16<lb> 

相比度量單位的這個缺點是,你必須手動打包和拆包代碼這些值,然後才能使用數字和有針對運行時成本太高。

+1

感謝您的明確解釋和指導。如何防止自動轉換爲輸入csv列的System.DateTime? – matekus

+1

查看[本頁]的「控制列類型」部分(http://fsharp.github.io/FSharp.Data/library/CsvProvider.html)。您可能需要製作自己的小示例文件,並在創建時將其傳遞給類型提示,然後加載實際文件以處理真實數據。 – TheQuickBrownFox

+0

我已經嘗試過這條路線,但沒有成功。 – matekus

0

我解決了輸入權重列的自動轉換爲System.DateTime如下:

// http://fssnip.net/27 
let lazySplit (sep:string) (str:string) = 
    match sep, str with 
    | ((null | ""), _) | (_, (null | "")) -> seq [str] 
    | _ -> 
     let n, j = str.Length, sep.Length 
     let rec loop p = 
     seq { 
      if p < n then 
      let i = match str.IndexOf(sep, p) with -1 -> n | i -> i 
      yield str.Substring(p, i - p) 
      yield! loop (i + j) 
     } 
     loop 0 

let weight input = 
    input 
    |> (fun x -> lazySplit "/" x |> Seq.take 2 |> String.concat("-")) 

let data = Weighings.GetSample() 
for row in data.Rows do 
    let stlbs = weight (string row.Weight) 
    printfn "Output: (%A, %A, %A)" row.Date row.Name stlbs 

// Output: 11-Sep-2017,"Alpha","09-01") 

感謝一個和所有的專家的幫助和指導。