F#使用while循环

时间:2010-06-05 14:51:49

标签: f#

我有一个datareader,我希望从中返回行集,在阅读了一天的书之后,我无法找到在f#中执行此操作的最佳方法。我可以在F#中以正常的C#方式进行,但这不是我使用f#

的原因

这是我想要实现的目标

let values =
    while reader.Read() do
        yield reader.GetString(0), reader.GetInt64(1)

以上就是我的尝试

  • 所有值都会被收集到值中,这些值可以是dictinary或元组或任何集合
  • yield不能在while循环中使用,但这就是我想要做的事情

实现这一目标的最佳途径是什么

5 个答案:

答案 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。