如何使用CSVProvider加载具有不同结构的CSV?

如何使用CSVProvider加载具有不同结构的CSV?,csv,f#,Csv,F#,有什么想法吗?我现在的代码如下 let rawdata csvfile FinCsv.Load(data).Rows |> Seq.filter (fun row -> row.Id <> "---") |> Seq.filter (fun row -> row.Country <> "Honduras") |> Seq.filter (fun row -> row.Ta

有什么想法吗?我现在的代码如下

let rawdata csvfile 
        FinCsv.Load(data).Rows
        |> Seq.filter (fun row -> row.Id <> "---")
        |> Seq.filter (fun row -> row.Country <> "Honduras")
        |> Seq.filter (fun row -> row.Tax <> 0)
        |> Seq.groupBy (fun row -> row.Country)
        |> Seq.averageBy (fun row -> row.Tax)
        |> List.ofSeq
让rawdata csvfile
FinCsv.Load(数据).Rows
|>Seq.filter(有趣的行->行Id“---”)
|>序号过滤器(趣味行->行国家“洪都拉斯”)
|>Seq.filter(乐趣行->税务0行)
|>Seq.groupBy(乐趣行->国家行)
|>Seq.averageBy(乐趣行->税务行)
|>表1.1

静态解析类型参数的问题在于语法很麻烦。下面是一个例子:

let inline snippet< ^T when ^T : (member Id : string)
                        and ^T : (member Country : string)
                        and ^T : (member Tax : float) >
                        xs =
    xs
    |> Seq.filter (fun row -> ( ^T : (member Id : string) row) <> "---")
    |> Seq.filter (fun row -> ( ^T : (member Country : string) row) <> "South America")
    |> Seq.filter (fun row -> ( ^T : (member Tax : float) row) <> 0.0)
    |> Seq.groupBy (fun row -> ( ^T : (member Country : string) row))
    |> Seq.map (fun (country, rows) -> country, (rows |> Seq.averageBy (fun row -> ( ^T : (member Tax : float) row))))
    |> List.ofSeq
然后,您的交换机可能如下所示:

let rawdata csvfile =
    match csvfile with
    | 1 -> snippetForCsvFile1 CsvFile1
    | 2 -> snippetForCsvFile2 CsvFile2
    | 3 -> snippetForCsvFile3 CsvFile3
    | 4 -> snippetForCsvFile4 CsvFile4
    | _ -> failwith "Not a File"
这应该适用于你的最后一个表达:

let raw =
    [ 1 .. 4]
    |> List.collect rawdata
您问题中的切换有一个问题,您在问题中没有提到:

let rawdata csvfile =
    let data = 
        match csvfile with
        | 1 -> CsvFile1
        | 2 -> CsvFile2
        | 3 -> CsvFile3
        | 4 -> CsvFile4
        | _ -> failwith "Not a File"

这里的问题是
数据的绑定没有单一类型。您可以通过使用接口(或基类)的面向对象方法实现这一点,但这对于F#来说并不是特别惯用的方法。一种更惯用的方法是声明一个有区别的联合,但鉴于您发布的示例,似乎没有必要这样做。

CSV提供程序使用列位置来提取数据。除非不同的CSV格式将
Id
Country
Tax
列作为同一顺序的前3列,否则您必须预处理文件以标准化格式,或者使用此处讨论的静态解析类型参数:在这种情况下,如何使用它们?链接是另一种情况。@AaronM.Eshbach还可以遵循面向对象的方法,声明接口和类型,以表示也实现接口的每个文件结构。对于功能更强大的方法,可以使用函数参数分别获取id、country和tax。不过,如果我不想把问题看得太重,我会倾向于静态解析类型参数的建议。说真的,从问题中删除文本和代码有什么意义?现在,人们花时间研究的答案是没有背景的!
let snippetForCsvFile1 (xs : CsvFile1 seq) = xs |> snippet2 (fun r -> r.Id) (fun r -> r.Country) (fun r -> r.Tax)
let rawdata csvfile =
    match csvfile with
    | 1 -> snippetForCsvFile1 CsvFile1
    | 2 -> snippetForCsvFile2 CsvFile2
    | 3 -> snippetForCsvFile3 CsvFile3
    | 4 -> snippetForCsvFile4 CsvFile4
    | _ -> failwith "Not a File"
let raw =
    [ 1 .. 4]
    |> List.collect rawdata
let rawdata csvfile =
    let data = 
        match csvfile with
        | 1 -> CsvFile1
        | 2 -> CsvFile2
        | 3 -> CsvFile3
        | 4 -> CsvFile4
        | _ -> failwith "Not a File"