如何使用 FSharp.Data 读取 csv
How to read in csv with FSharp.Data
我正在按照此处的示例尝试使用 FSharp.Data 中的 CsvProvider:http://fsharp.github.io/FSharp.Data/library/CsvProvider.html
在示例中,他们定义了一个类型,然后使用该类型,但看起来他们是在交互模式下进行的。我正在尝试在我的 main 中做同样的事情,但我不明白为什么它不起作用。
在示例中,他们执行以下操作:
type Stocks = CsvProvider<"../data/MSFT.csv">
这是我的尝试:
open System
open System.IO
open FSharp.Data
// Process execution params
// args(0) = nesting level
// args(1) = csv file name
[<EntryPoint>]
let main (args: string[]) =
printfn "Arguments passes in: %A" args
// F# searches the following directory at runtime : C:\Users\userName\source\repos\crawlerF\crawlerF\bin\Debug\netcoreapp2.1\test.csv'.
// It is therefore necessary to provide the top level of the repo for the file read by prepending ../../../../ to the file name
let filePath = "../../../../" + args.[1]
type urls = CsvProvider<filePath>
0
当我尝试定义 urls 变量时遇到一些语法错误。为什么会这样?我是 F# 的新手,所以我将不胜感激。
谢谢。
这里发生了一些事情:
您不能在函数内定义类型,因此您需要将 urls
的定义移出 main
函数并移至模块或命名空间中。
类型提供程序为您提供了一种生成类型的简单方法,而不是您自己手动定义它们,但是这些类型仍然需要在 compile-time 处生成。这意味着您传递给类型提供程序的任何参数都必须是静态的,即必须具有 compile-time.
的值
在您的例子中,示例 CSV 文件的 filePath
是您传递给 CsvProvider
的唯一参数,但因为该值是从命令行参数派生的,所以它只是在运行时已知。要将静态文件名传递给 CsvProvider
,您可以使用文字字符串,例如
// Option 1: Use an inline literal string, like in the example from FSharp.Data.
type Urls = CsvProvider<"test.csv">
// Option 2: Use a named literal so that the compiler knows this value is static.
let [<Literal>] FilePath = "test.csv"
type Urls = CsvProvider<FilePath>
这可能只是代码示例中的格式错误,但为了 return 来自 main
函数的 0
,它必须缩进以便它被识别为该代码块的最后一个表达式。
将所有这些放在一起可以得出如下结果:
open FSharp.Data
module Program =
// The `Urls` type is now defined within a module.
// This type is generated at compile-time from the sample file.
// Assumes the sample file 'test.csv' exists in the project folder at compile-time.
type Urls = CsvProvider<"test.csv">
[<EntryPoint>]
let main args =
// Use the generated `Urls` type to load some data at runtime.
let urls = Urls.Load("...")
// ...
// Return an integer exit code.
0
我正在按照此处的示例尝试使用 FSharp.Data 中的 CsvProvider:http://fsharp.github.io/FSharp.Data/library/CsvProvider.html
在示例中,他们定义了一个类型,然后使用该类型,但看起来他们是在交互模式下进行的。我正在尝试在我的 main 中做同样的事情,但我不明白为什么它不起作用。
在示例中,他们执行以下操作:
type Stocks = CsvProvider<"../data/MSFT.csv">
这是我的尝试:
open System
open System.IO
open FSharp.Data
// Process execution params
// args(0) = nesting level
// args(1) = csv file name
[<EntryPoint>]
let main (args: string[]) =
printfn "Arguments passes in: %A" args
// F# searches the following directory at runtime : C:\Users\userName\source\repos\crawlerF\crawlerF\bin\Debug\netcoreapp2.1\test.csv'.
// It is therefore necessary to provide the top level of the repo for the file read by prepending ../../../../ to the file name
let filePath = "../../../../" + args.[1]
type urls = CsvProvider<filePath>
0
当我尝试定义 urls 变量时遇到一些语法错误。为什么会这样?我是 F# 的新手,所以我将不胜感激。
谢谢。
这里发生了一些事情:
您不能在函数内定义类型,因此您需要将
urls
的定义移出main
函数并移至模块或命名空间中。类型提供程序为您提供了一种生成类型的简单方法,而不是您自己手动定义它们,但是这些类型仍然需要在 compile-time 处生成。这意味着您传递给类型提供程序的任何参数都必须是静态的,即必须具有 compile-time.
的值在您的例子中,示例 CSV 文件的
filePath
是您传递给CsvProvider
的唯一参数,但因为该值是从命令行参数派生的,所以它只是在运行时已知。要将静态文件名传递给CsvProvider
,您可以使用文字字符串,例如// Option 1: Use an inline literal string, like in the example from FSharp.Data. type Urls = CsvProvider<"test.csv">
// Option 2: Use a named literal so that the compiler knows this value is static. let [<Literal>] FilePath = "test.csv" type Urls = CsvProvider<FilePath>
这可能只是代码示例中的格式错误,但为了 return 来自
main
函数的0
,它必须缩进以便它被识别为该代码块的最后一个表达式。
将所有这些放在一起可以得出如下结果:
open FSharp.Data
module Program =
// The `Urls` type is now defined within a module.
// This type is generated at compile-time from the sample file.
// Assumes the sample file 'test.csv' exists in the project folder at compile-time.
type Urls = CsvProvider<"test.csv">
[<EntryPoint>]
let main args =
// Use the generated `Urls` type to load some data at runtime.
let urls = Urls.Load("...")
// ...
// Return an integer exit code.
0