如何使用 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# 的新手,所以我将不胜感激。

谢谢。

这里发生了一些事情:

  1. 您不能在函数内定义类型,因此您需要将 urls 的定义移出 main 函数并移至模块或命名空间中。

  2. 类型提供程序为您提供了一种生成类型的简单方法,而不是您自己手动定义它们,但是这些类型仍然需要在 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>
    
  3. 这可能只是代码示例中的格式错误,但为了 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