我尝试在F#中做一些图表。作为输入,我有CSV文件,其中有一些值可以为空(例如nullable int)。我尝试使用以下代码显示图表:
[for row in data.Rows -> row.A.Value, row.B.Value] |> Chart.Point
A和B都是可以为空的整数。我收到以下错误
System.InvalidOperationException:Nullable对象必须具有值。
我应该如何处理可空类型。我应该写一些Option类型来处理它,或者还有其他一些好的方法来解决它。
答案 0 :(得分:4)
如果您使用的是F#4.0,则内置函数Option.ofNullable
。如果不是,那么您可以在其他答案中使用该实现。
您也可以使用相同的代码来定义活动模式:
let (|Present|_|) (n:System.Nullable<_>) =
if n.HasValue then Some(n.Value)
else None
...这可以在match
构造中使用,因此您可以编写:
[ for row in data.Rows do
match row.A, row.B wih
| Present a, Present b -> yield a,b
| _ -> () ] |> Chart.Point
答案 1 :(得分:3)
将Nullable类型映射到Option类型并将其过滤掉(使用.filter或.choose)或将None转换为缺失值的特殊值(例如0,-1,NaN),具体取决于您的数据以使其工作在图表工具中。
module Option =
let fromNullable (n: _ Nullable) =
if n.HasValue
then Some n.Value
else None
答案 2 :(得分:3)
你出错的地方是:你在可能为空的东西上调用Value
属性。
当你打电话给Value
时,你实际上是在说“没关系,我已经严格改变了这个值,并且它绝对不是空的所以把它当作非非法处理是完全安全的 - 可以接受的价值。“当然,在这种情况下,不满足该条件,因此运行时异常。
在F#中,您不想使用Nullable<'T>
类型,您希望使用Option<'T>
,这样更安全,编译器可以更有效地检查您是不是犯了错误。
您可以使用
将列表从Nullable<'T>
转换为Option<'T>
[for row in data.Rows -> Option.ofNullable (row.A), Option.ofNullable(row.B)]
当然,你必须决定如何处理None
个案,但是一旦你的设计明确地告诉你你有可能或者可能的值,那么这样做会容易得多不是什么。
我不知道你想要什么行为但是,作为一个例子,也许您只想绘制两个值都有效的情况?
您可以压缩两个选项值:
module Option =
let zip a b =
match (a,b) with
|Some sa, Some sb -> Some(sa, sb)
|_ -> None
然后,您可以回映到可绘制的数字,使用None
提取List.choose
个案例。
[for row in data.Rows -> Option.ofNullable (row.A), Option.ofNullable (row.B)]
|> List.choose (fun (a,b) -> Option.zip a b)
|> Chart.Point