F# 初始化类的函数方法
我对F#还不熟悉,所以我热衷于尝试以更实用的方式来处理问题(而不是用我习惯的命令式思维) 对于这个问题,我正在从Excel中读取数据,其中包含约6000行数据,包含多个字段(年龄、性别、性别等) 我正在使用一个类将这些数据点存储在下面的-extract中:F# 初始化类的函数方法,f#,functional-programming,F#,Functional Programming,我对F#还不熟悉,所以我热衷于尝试以更实用的方式来处理问题(而不是用我习惯的命令式思维) 对于这个问题,我正在从Excel中读取数据,其中包含约6000行数据,包含多个字段(年龄、性别、性别等) 我正在使用一个类将这些数据点存储在下面的-extract中: type datastore(array:obj[,], row)= let id=array.[row,1]:?> string; let gender=array.[row,2] :?> string;
type datastore(array:obj[,], row)=
let id=array.[row,1]:?> string;
let gender=array.[row,2] :?> string;
let sex = array.[row,3] :?> string;
//...continues for a number of other cases
我目前正在使用以下代码初始化这些类,这些代码运行良好,但这是一种必要的方法:
let DataPoints =
let DataInput = //function to read data in from Excel
[for i in DataInput.GetLowerBound(0) .. DataInput.GetUpperBound(0) ->
new datastore(DataInput,i)]
我的问题是,我如何才能以一种更实用的方式做到这一点
我尝试了以下方法(不起作用:给出的错误只是“由于错误而停止”)
我还查看了以下链接,这些链接似乎没有完全帮助
我不会说它“功能更少或更强大”<代码>数据点在第二个代码段中是一个列表,其中包含由F#机制初始化的数据存储
值
如果希望DataPoints
改为数据存储
值的数组,由标准库函数初始化,相应的代码可能如下所示
let DataPoints =
let (il,ih) = (DataInput.GetLowerBound(0),DataInput.GetUpperBound(0)) in
Array.init (ih - il + 1) (fun x -> new datastore(DataInput, x + il))
为了采用给定的Array.init
元素索引处理,从0
到元素数-1
到DataInput.GetLowerBound(0)
到DataInput.GetUpperBound(0)-DataInput.GetLowerBound(0)
但这两种方法都是函数式编程的一种形式,用于生成元素序列。我不会将其称为“少功能或多功能”<代码>数据点在第二个代码段中是一个列表,其中包含由F#机制初始化的数据存储
值
如果希望DataPoints
改为数据存储
值的数组,由标准库函数初始化,相应的代码可能如下所示
let DataPoints =
let (il,ih) = (DataInput.GetLowerBound(0),DataInput.GetUpperBound(0)) in
Array.init (ih - il + 1) (fun x -> new datastore(DataInput, x + il))
为了采用给定的Array.init
元素索引处理,从0
到元素数-1
到DataInput.GetLowerBound(0)
到DataInput.GetUpperBound(0)-DataInput.GetLowerBound(0)
但这两种方法都是函数式编程的形式,用于生成元素序列。函数式编程是每个人都有自己的定义的东西之一。如果你问我,两个突出的品质是:
- 从类型的角度思考问题(称之为类型驱动、类型优先编程或其他)
- 将逻辑视为由可组合步骤组成的数据转换管道
type DataPoint =
{
Id: string
Gender: GenderType
Sex: SexType
}
static member FromRow(row: obj []) =
{
Id = row.[0] :?> string
Gender = GenderType.Parse <| (row.[1] :?> string)
Sex = SexType.Parse <| (row.[2] :?> string)
}
有了这些,我们就有了所需的一切,现在就把它们放在一条管道中:
let dataPoints =
let input = //function to read data in from Excel
input
|> Array2D.intoRows
|> Seq.map DataPoint.FromRow
|> Array.ofSeq
这样就很容易看到发生了什么。您可以在每个步骤中轻松地剖析数据,扩展代码也很简单。例如,如果要将这些记录转换为一个类(例如viewmodel),这只是要添加到此处的另一个
map
步骤 函数式编程是每个人都有自己定义的东西之一。如果你问我,两个突出的品质是:
- 从类型的角度思考问题(称之为类型驱动、类型优先编程或其他)
- 将逻辑视为由可组合步骤组成的数据转换管道
type DataPoint =
{
Id: string
Gender: GenderType
Sex: SexType
}
static member FromRow(row: obj []) =
{
Id = row.[0] :?> string
Gender = GenderType.Parse <| (row.[1] :?> string)
Sex = SexType.Parse <| (row.[2] :?> string)
}
有了这些,我们就有了所需的一切,现在就把它们放在一条管道中:
let dataPoints =
let input = //function to read data in from Excel
input
|> Array2D.intoRows
|> Seq.map DataPoint.FromRow
|> Array.ofSeq
这样就很容易看到发生了什么。您可以在每个步骤中轻松地剖析数据,扩展代码也很简单。例如,如果要将这些记录转换为一个类(例如viewmodel),这只是要添加到此处的另一个
map
步骤 使用ExcelProvider:感谢链接。如果我继续我目前的方法,你对我的具体问题有什么更一般的指导吗?你的代码看起来不错。为什么你认为这是必要的?使用ExcelProvider:谢谢你的链接。如果我继续我目前的方法,你对我的具体问题有什么更一般的指导吗?你的代码看起来不错。为什么你认为这是必要的?如果我想使用Array.init
,我会这么做,但值得注意的是,在这种情况下,列表理解看起来简单多了:-)如果我想使用Array.init
,我会这么做,但值得注意的是,在这种情况下,这份清单的理解看起来简单多了:-)性别和性别都太复杂了,无法用一个歧视性的结合来正确处理。在大多数情况下,最好不要与他们打交道!性别和性别都太复杂了,无法在一个受歧视的联盟中妥善处理。在大多数情况下,最好不要与他们打交道!