【问题标题】:Get the column type information from CsvProvider?从 CsvProvider 获取列类型信息?
【发布时间】:2015-08-15 08:33:35
【问题描述】:

我有以下代码来获取 CSV 文件的类型信息。如何获取列的类型信息?我需要将它保存到数据库表中。

open FSharp.Data

type MyFile = CsvProvider<"""C:\temp\sample.csv""">

[<EntryPoint>]
let main argv = 
    let myFile = MyFile.Load("""C:\temp\sample.csv""")

    printfn "%A" ((myFile.Rows |> Seq.head).GetType())
    // Write the type information of myFile columns to a table

    for row in myFile.Rows do
        printfn "%A" row
    0 

函数((myFile.Rows |&gt; Seq.head).GetType()) 返回基本 F# 类型的嵌入元组,并且缺少标头名称。

System.Tuple`8[System.Int32,System.Int32,System.String,System.Int32,System.Int32 ,System.String,System.String,System.Tuple`8[System.Int32,System.String,System.De cimal,System.Decimal,System.Decimal,System.Decimal,System.Int32,System.Tuple`8[S ystem.Decimal,System.Decimal,System.Decimal,System.Nullable`1[System.Int32],Syst em.String,System.Boolean,System.Int32,System.Tuple`8[System.Decimal,System.Int32 ,System.Int32,System.Decimal,System.Int32,System.Nullable`1[System.Int32],System .Int32,System.Tuple`8[System.Decimal,System.Nullable`1[System.Int32],System.Null 能够`1[System.Int32],System.Nullable`1[System.Int32],System.Decimal,System.Decim al,System.String,System.Tuple`8[System.String,System.String,System.String,System .String,System.String,System.String,System.String,System.Tuple`8[System.String,S ystem.String,System.String,System.String,System.String,System.String,System.Null 能够`1[System.Int32],System.Tuple`8[System.String,System.String,System.Nullable` 1[System.Int32],System.String,System.String,System.String,System.String,System.T uple`8[System.String,System.String,System.String,System.String,System.String,Sys tem.String,System.String,System.Tuple`1[System.String]]]]]]]]]]

预期输出,

ColumnA int
ColumnB datetime
ColumnC varchar
....

【问题讨论】:

  • 旁注:如果您从提供给类型提供程序的同一个文件加载,您可以调用GetSample() 而不是Load("file name")
  • 太棒了。 GetSample() 在这种情况下很好。

标签: f# f#-data


【解决方案1】:

我相信有人可以提供一种更惯用的方式来组织它,但这至少应该有效(还要注意,我明确没有进行任何异常处理和访问 string [] option 值 (Headers) 的值) .出于格式化目的,参数位于新行上,仅供参考。:

let rec iterateTupleMemberTypes (tupleArgTypes: System.Type[]) 
    (columnNames: string[]) 
    (startingIndex : int) =
    let mutable index = startingIndex
    for t in tupleArgTypes do
        match t.IsGenericType with
        | true -> iterateTupleMemberTypes (t.GetGenericArguments()) columnNames index
        | false ->
            printfn "Name: %s Type: %A" (columnNames.[index]) t
            index <- index + 1

然后这样称呼它:

let firstRow = MyFile.Rows |> Seq.head
let tupleType = firstRow.GetType()
let tupleArgTypes = tupleType.GetGenericArguments()
iterateTupleMemberTypes tupleArgTypes MyFile.Headers.Value 0

iterateTupleMemberTypes 的递归性质是必要的,因为一旦您的元组达到一定数量的“成员”,最后一个成员就会用于将所有剩余成员填充到自己的元组中。在我的测试中,这发生在我命中元组的 8 个成员时。

编辑

OP 在 cmets 中询问如何修改 iterateTupleMemberTypes 以构建类型/名称对的集合,这就是(我决定将它们作为元组):

let iterateTupleMemberTypes (tupleArgTypes: System.Type[]) (columnNames: string[]) =
    let rec iterateRec (argTypes: System.Type list) (values) (index) =
        match argTypes with
        | [] -> List.rev values
        | head :: tail when head.IsGenericType -> 
            iterateRec (List.ofArray (head.GetGenericArguments())) values index
        | head :: tail -> 
            iterateRec tail ((head, columnNames.[index])::values) (index + 1)
    iterateRec (List.ofArray tupleArgTypes) List.empty 0

这样称呼它:

let tupleType = firstRow.GetType()
let tupleArgTypes = tupleType.GetGenericArguments()
let schemaStuff = iterateTupleMemberTypes tupleArgTypes MyFile.Headers.Value

作为额外的奖励方法,您可以通过以下方式迭代这些结果元组:

let rec printSchemaMembers (schema:(System.Type*string) list) =
    match schema with
    | (argType, name)::tail ->
        printfn "Type: %A, Name: %s" argType name
        printSchemaMembers tail
    | [] -> ignore

【讨论】:

  • 听起来不错。如何更新函数iterateTupleMemberTypes 以返回ColumnName 和类型的dict/map
  • 我在这里发布了一个答案:stackoverflow.com/a/30590166/2894770 嵌套元组从 8 列开始,因为 System.Tuples 最多有 8 个通用参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
相关资源
最近更新 更多