F#使用while循环
我有一个datareader,我想返回其中的行集合,在读了一天的书之后,我无法找到用f#实现它的最佳方法。我可以用普通的C#方式用F#完成,但这不是我使用F的原因# 以下是我正在努力实现的目标F#使用while循环,f#,F#,我有一个datareader,我想返回其中的行集合,在读了一天的书之后,我无法找到用f#实现它的最佳方法。我可以用普通的C#方式用F#完成,但这不是我使用F的原因# 以下是我正在努力实现的目标 let values = while reader.Read() do yield reader.GetString(0), reader.GetInt64(1) 以上就是我试图做的 所有值都被收集到值中,这些值可以是字典、元组或任何集合 在while循环中不能使用yield,
let values =
while reader.Read() do
yield reader.GetString(0), reader.GetInt64(1)
以上就是我试图做的
- 所有值都被收集到值中,这些值可以是字典、元组或任何集合
- 在while循环中不能使用yield,但这正是我要做的
实现这一点的最佳方法是什么?您可以使用序列表达式实现枚举数:
let records = seq { while reader.NextResult() do yield (reader.GetString(0), reader.GetInt64(1)) }
如果需要两个以上的字段,可以生成列索引(或名称)->字段值(未测试代码)的映射:
让dbSchema=reader.GetSchemaTable()
let makeMap(rdr:IDataReader)(模式:DataTable)=
schema.Columns |>Seq.cast |>Seq.map(fun col->(col.ColumnName,rdr.[col.ColumnName]))|>map.ofSeq
让records=seq{while reader.NextResult()不产生(makeMap reader dbSchema)}
对于此类任务,我想首先将输入转换为字符串序列
.Net 4.0提供读取行,其返回值的类型为seq
:
在.Net的较低版本中,需要实现以下功能:
let readLines filePath = seq {
use sr = new StreamReader (filePath)
while not sr.EndOfStream do
yield sr.ReadLine ()
}
我们这里不讨论文件,但是,在早期的.NET版本中,您可以(使用小文件): 其中,
reader
是文本阅读器。F#还提供数组和序列的列表理解
let records_as_list =
[
while reader.Read()
do yield (reader.GetString(0), reader.GetInt64(1))
]
let records_as_array =
[|
while reader.Read()
do yield (reader.GetString(0), reader.GetInt64(1))
|]
let records_as_sequence =
seq {
while reader.Read()
do yield (reader.GetString(0), reader.GetInt64(1))
}
F#内置了一个方便的字典功能,名为dict
let records_as_IDictionary = dict records_as_sequence
我可以通过向
IDataReader
添加一个扩展属性来更一般地处理这个问题,该属性将任何数据读取器转换为seq
[<AutoOpen>]
module DataReaderEx =
open System.Data
type IDataReader with
member this.toSeq =
seq { while this.Read() do yield this :> IDataRecord }
如果文件很大,则应避免读取所有内容和拆分。在这个问题中,
reader
实际上是一个IDataReader,而不是TextReaderies,基本思想是一样的。seq的问题是它会延迟加载,所以在这种情况下,当您想要阅读它时,阅读器会通过在最后一行添加|>seq.toList来实现集合,从而彻底修复。
let records_as_list =
[
while reader.Read()
do yield (reader.GetString(0), reader.GetInt64(1))
]
let records_as_array =
[|
while reader.Read()
do yield (reader.GetString(0), reader.GetInt64(1))
|]
let records_as_sequence =
seq {
while reader.Read()
do yield (reader.GetString(0), reader.GetInt64(1))
}
let records_as_IDictionary = dict records_as_sequence
[<AutoOpen>]
module DataReaderEx =
open System.Data
type IDataReader with
member this.toSeq =
seq { while this.Read() do yield this :> IDataRecord }
reader.toSeq
|> Seq.map (fun row -> row.GetString(0), row.GetInt64(1))