从 CsvProvider 获取列类型信息?
Get the column type information from CsvProvider?
我有以下代码来获取 CSV 文件的类型信息。如何获取列的类型信息?我需要将它保存到数据库 table.
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 |> Seq.head).GetType())
returns 基本 F# 类型的嵌入式元组和 header 名称丢失。
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
able`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
able`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
....
我相信有人可以提供一种更惯用的方式来组织这个,但这至少应该有效(另请注意,我明确地没有做任何异常处理和访问 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
的递归性质是必要的,因为一旦您的元组达到一定数量 "members",最后一个成员将用于将所有剩余成员填充到它自己的元组中。在我的测试中,一旦我命中元组的 8 个成员,就会发生这种情况。
编辑
OP 在评论中询问如何修改 iterateTupleMemberTypes
以构建 type/name 对的集合,这里就是(我决定将它们作为元组):
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
我有以下代码来获取 CSV 文件的类型信息。如何获取列的类型信息?我需要将它保存到数据库 table.
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 |> Seq.head).GetType())
returns 基本 F# 类型的嵌入式元组和 header 名称丢失。
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 able`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 able`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
....
我相信有人可以提供一种更惯用的方式来组织这个,但这至少应该有效(另请注意,我明确地没有做任何异常处理和访问 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
的递归性质是必要的,因为一旦您的元组达到一定数量 "members",最后一个成员将用于将所有剩余成员填充到它自己的元组中。在我的测试中,一旦我命中元组的 8 个成员,就会发生这种情况。
编辑
OP 在评论中询问如何修改 iterateTupleMemberTypes
以构建 type/name 对的集合,这里就是(我决定将它们作为元组):
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