【问题标题】:F# sequences returning one item at a timeF# 序列一次返回一项
【发布时间】:2019-12-25 18:36:21
【问题描述】:

我是 F# 的新手,我正在尝试将 DbDataReader 类从 c# 转换为 F#,DBDataReader 读取并返回一个 csv 行作为列表

member this.ReadCSV = 
    seq { 
        use textReader = File.OpenText(filename)
        while (not textReader.EndOfStream) do
            let line = textReader.ReadLine()
            // linedata is a class variable that holds the current data for use by DBDataReader
            linedata <- line |> Seq.toList |> splitDelimited delimiter "" [])
            yield true
        yield false
    }

DBDataReader 类有一个 Read() 函数,调用该函数时应该将光标移动到输入中的下一行,我使用如下索引变量实现了这一点,但在处理具有数百万行的文件时这似乎效率低下。有没有更有效的方法?

override this.Read() =
    let hasRows = Seq.item idx this.ReadCSV
    idx <- idx + 1
    hasRows

【问题讨论】:

  • 您是否考虑过使用 Csv 类型提供程序? fsharp.github.io/FSharp.Data/library/CsvProvider.html
  • 我已经查看了 CSV 类型提供程序,但它有同样的问题,因为 DBDataReader 类要求读取函数将读取指针推进到下一条记录,我找不到简单的方法用 F# 中的序列来做到这一点

标签: f# c#-to-f#


【解决方案1】:

为什么不使用枚举器而不是序列?

如果你真的想使用 FP 风格的序列,那么

  1. 从序列和收益期权值
  2. 将使用this.Read() 方法的循环语句替换为使用this.ReadCSV 作为可枚举表达式的for..in 表达式和
member this.CSV = 
    seq { 
        use textReader = File.OpenText(filename)
        while (not textReader.EndOfStream) do
            let line = textReader.ReadLine()
            yield (line |> Seq.toList |> splitDelimited delimiter "" [])
    }


for linedata in this.CSV do
    ...

【讨论】:

  • 谢谢,但是 read() 函数被外部​​程序使用,我无法控制它。
  • 在这种情况下,您可以将序列转换为 IEnumerator(例如 member this.CSV = (seq { ...}).GetEnumerator())并使用枚举器 MoveNext()Current 来实现 Read() 方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多