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

发布于 2024-09-02 20:45:25 字数 567 浏览 8 评论 0原文

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

I have a function that will parse the results of a DataReader, and I don't know how many items are returned, so I want to use a while..do loop to iterate over the reader, and the outcome should be a list of a certain type.

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

This is what I tried, but the warning I get is:

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.

So what is the best way to iterate over a DataReader and create a list?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

揽月 2024-09-09 20:45:25

您可以使用列表理解:

[
   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!),这里是一个使用的示例欧拉项目 31

you can use list comprehension:

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

Here is one more example:

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

or

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

You can also do it for sequences and arrays:

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

you can also yield a sub sequence in a sequence(yield!), here is an example using Project Euler 31.

缪败 2024-09-09 20:45:25

只是为了提供一些可以解释这里发生的情况的附加信息 - 在 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 ]

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

Just to provide some additional information that may explain what is going on here - there are two ways of creating lists in F# and in both cases, you're writing something in square braces [ ... ] (which may be a bit confusing at first!)

List literals are used when you have a few expressions (known number of explicitly written expressions) and want to create a list containing the results of evaluating these expressions. For example:

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

List comprehensions are used when you have some code that does something and generates list of elements (by producing elements during the calculation). This is what Yin Zhu uses in his answer. Some examples are:

[ 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

Advanced features
You can also use yield! to generate multiple elements at once:

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

This can be used for writing recursive functions, so you could rewrite your code using recursion instead of loop (this would be useful if you needed to keep some state, but as your code looks currently, while is perfectly fine!)

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 ]

This is a pattern that often appears in list comprehensions, so it is useful to know about it :-).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文