Как инициализировать список F #, когда размер неизвестен, используя цикл while..do - PullRequest
2 голосов
/ 24 мая 2010

У меня есть функция, которая будет анализировать результаты 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 и создать список?

Ответы [ 2 ]

9 голосов
/ 24 мая 2010

Вы можете использовать понимание списка:

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

6 голосов
/ 24 мая 2010

Просто для предоставления дополнительной информации, которая может объяснить, что здесь происходит - в 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 ]

Это шаблон, который часто встречается в списках, поэтому полезно знать об этом: -).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...