2

我有一个函数会解析DataReader的结果,我不知道返回了多少项目,所以我想用一个while..do循环来遍历阅读器,结果应该是某种类型的列表。

(fun(reader) ->
            [
                while reader.Read() do
                    new CityType(Id=(reader.GetInt32 0), Name=(reader.GetString 1), StateName=(reader.GetString 2))
            ])

这是我尝试过的,但我得到的警告是:

This expression should have type 'unit', but has type 'CityType'. Use 'ignore' to discard the result of the expression, or 'let' 
to bind the result to a name.

那么迭代 DataReader 并创建列表的最佳方法是什么?

4

2 回答 2

10

您可以使用列表理解:

[
   while reader.Read() do
       let d =  new CityType(Id=(reader.GetInt32 0), Name=(reader.GetString 1), StateName=(reader.GetString 2))
       yield d
]

这里还有一个例子:

/// The squares of the first 10 integers
let squaresOfOneToTen = [ for x in 0..10 -> x*x ]

或者

let squaresOfOneToTen = [ for x in 0..10 do yield x*x ]

您也可以对序列和数组执行此操作:

seq { 
   for i=1 to 9 do 
      for j=1 to 9 do
         yield (i,j,i*j)
}


[| for i=1 to 100 do yield i*i |]

你也可以在 sequence() 中产生一个子序列yield!,这里是一个使用Project Euler 31的例子。

于 2010-05-24T02:43:56.980 回答
6

只是为了提供一些可以解释这里发生的事情的额外信息 - 在 F# 中有两种创建列表的方法,在这两种情况下,您都在方括号中编写一些东西[ ... ](一开始可能有点令人困惑!)

当您有几个表达式(已知数量的显式编写的表达式)并且想要创建一个包含评估这些表达式的结果的列表时,使用列表文字。例如:

[ 1; 2; 3; ]       // list of constant expressions
[ 1+1; 2+2; 3+3 ]  // creates list [ 2; 4; 6 ]

当您有一些代码执行某些操作并生成元素列表(通过在计算期间生成元素)时,使用列表推导这就是殷竹在他的回答中使用的。一些例子是:

[ yield 1; ]           // generates singleton list [ 1 ] 
[ yield 1; yield 2; ]  // generates list with two elements
[ for x in 1 .. 10 do  // iterates loop 10 times
    yield x * x ]      // ... generates element during every iteration

高级功能
您还可以使用yield!一次生成多个元素:

[ yield! [ 1; 2 ]      // generates a list containing [ 1; 2; 3; 4 ]
  yield! [ 3; 4 ] ]

这可用于编写递归函数,因此您可以使用递归而不是循环来重写代码(如果您需要保持某些状态,这将很有用,但您的代码目前看起来while非常好!)

let rec loop reader = 
  [ if reader.Read() then
      yield new CityType(Id=(reader.GetInt32 0), Name=(reader.GetString 1), 
                         StateName=(reader.GetString 2))   
      yield! loop reader ]

这是一种经常出现在列表推导中的模式,因此了解它很有用:-)。

于 2010-05-24T02:54:27.490 回答