如何在大小未知时使用 while..do 循环初始化 F# 列表

Posted

技术标签:

【中文标题】如何在大小未知时使用 while..do 循环初始化 F# 列表【英文标题】:How to initialize F# list when size is unknown, using while..do loop 【发布时间】:2010-05-24 02:32:12 【问题描述】:

我有一个函数会解析 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 并创建列表的最佳方法是什么?

【问题讨论】:

我正试图找出完全相同的事情。很高兴你问。 +1 【参考方案1】:

您可以使用列表推导:

[
   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 |]

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

【讨论】:

感谢您的帮助。我忘记了 yield 关键字。【参考方案2】:

只是为了提供一些额外的信息来解释这里发生了什么 - 在 F# 中有两种创建列表的方法,在这两种情况下,您都在方括号 [ ... ] 中编写 something (一开始可能有点混乱!)

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

[ 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 ]

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

【讨论】:

非常感谢您提供更多信息。我期望的最后一部分很快就会非常有用。 来自真正的 F# 专家!最近看了很多你的文章。谢谢:)

以上是关于如何在大小未知时使用 while..do 循环初始化 F# 列表的主要内容,如果未能解决你的问题,请参考以下文章

while,do while,for循环语句

循环语句 while,do while ,for 循环

04循环结构(while/do-while/for)

03JAVA循环结构

03JAVA循环结构

while do while以及穷举和迭代