F# - 重量(计量单位)英石-磅
F# - Weight (Unit of Measure) Stones-Pounds
我有一个包含每日体重的 csv 文件,如下所示:
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
是否可以创建计量单位 (UoM) 来定义 "stlb" 并可选择在导入时转换为磅,如果可以,如何?
我认为您不能将石头-磅表示为单一的数字类型,并且度量单位只能用于数字类型(尽管 some discussion 将来会对此进行更改)。这是因为它们的某些功能仅对加法和乘法等数字运算有意义。单位本身乘除:
[<Measure>] type lb
2<lb> + 2<lb> // 4<lb>
2<lb> * 2<lb> // 4<lb ^ 2>
2<lb> / 2<lb> // 1
如果您希望某种标签知道给定值的类型为 stones-pounds,而不是度量单位,您可以创建一个区分大小写的联合:
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>
与度量单位相比,它的缺点是您必须在代码中手动打包和解包这些值,然后才能使用这些数字,而且这也会产生运行时成本。
我解决了输入权重列自动转换为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")
感谢大家的专家帮助和指导。
我有一个包含每日体重的 csv 文件,如下所示:
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
是否可以创建计量单位 (UoM) 来定义 "stlb" 并可选择在导入时转换为磅,如果可以,如何?
我认为您不能将石头-磅表示为单一的数字类型,并且度量单位只能用于数字类型(尽管 some discussion 将来会对此进行更改)。这是因为它们的某些功能仅对加法和乘法等数字运算有意义。单位本身乘除:
[<Measure>] type lb
2<lb> + 2<lb> // 4<lb>
2<lb> * 2<lb> // 4<lb ^ 2>
2<lb> / 2<lb> // 1
如果您希望某种标签知道给定值的类型为 stones-pounds,而不是度量单位,您可以创建一个区分大小写的联合:
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>
与度量单位相比,它的缺点是您必须在代码中手动打包和解包这些值,然后才能使用这些数字,而且这也会产生运行时成本。
我解决了输入权重列自动转换为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")
感谢大家的专家帮助和指导。