我有一个datareader,我希望从中返回行集,在阅读了一天的书之后,我无法找到在f#中执行此操作的最佳方法。我可以在F#中以正常的C#方式进行,但这不是我使用f#
的原因这是我想要实现的目标
let values =
while reader.Read() do
yield reader.GetString(0), reader.GetInt64(1)
以上就是我的尝试
实现这一目标的最佳途径是什么
答案 0 :(得分:14)
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
答案 1 :(得分:7)
您可以使用序列表达式来实现枚举器:
let records = seq { while reader.NextResult() do yield (reader.GetString(0), reader.GetInt64(1)) }
如果您需要两个以上的字段,则可以生成列索引(或名称)的地图 - >字段值(未经测试的代码):
let dbSchema = reader.GetSchemaTable()
let makeMap (rdr : IDataReader) (schema : DataTable) =
schema.Columns |> Seq.cast<DataColumn> |> Seq.map (fun col -> (col.ColumnName, rdr.[col.ColumnName])) |> Map.ofSeq
let records = seq { while reader.NextResult() do yield (makeMap reader dbSchema) }
答案 2 :(得分:3)
对于这种任务,我想首先将输入转换为字符串序列。
.Net 4.0提供了ReadLines,其返回值的类型为seq<string>
:
open System.IO
let readLinesSeq = File.ReadLines
在较低版本的.Net中,需要实现此功能:
let readLines filePath = seq {
use sr = new StreamReader (filePath)
while not sr.EndOfStream do
yield sr.ReadLine ()
}
答案 3 :(得分:2)
我可以通过向IDataReader
添加扩展属性来更一般地解决此问题,将任何datareader转换为seq<IDataRecord>
...
[<AutoOpen>]
module DataReaderEx =
open System.Data
type IDataReader with
member this.toSeq =
seq { while this.Read() do yield this :> IDataRecord }
这将允许您在任何datareader上使用Seq
模块中的普通函数:
reader.toSeq
|> Seq.map (fun row -> row.GetString(0), row.GetInt64(1))
答案 4 :(得分:0)
我们不是在讨论这里的文件,但是,在早期的.NET版本中你可以做(使用小文件):
reader.ReadToEnd().Split(System.Environment.NewLine.ToCharArray())
reader
是TextReader。