F # - Свести список / диапазон - PullRequest
3 голосов
/ 25 октября 2010

Я новичок в F # и мне интересно, как бы я сгладил список.

По сути, в базе данных я храню запись с диапазоном min_age и max_age (это вымышленный пример для краткости - я не агист!). Мои поля выглядят примерно так:

идентификатор, Стоимость, сбережения, min_age, max_age

По сути, у меня есть класс F #, который действует как однозначное сопоставление с этой таблицей - то есть все свойства отображаются точно в поля базы данных.

Я бы хотел сгладить этот диапазон. Итак, вместо списка, содержащего такие элементы:

saving_id = 1, cost = 100, savings = 20, min_age = 20, max_age = 26
saving_id = 2, cost = 110, savings = 10, min_age = 27, max_age = 31

Я хотел бы список, содержащий элементы, подобные этому:

saving_id = 1, cost = 100, savings = 20, age = 20
saving_id = 1, cost = 100, savings = 20, age = 21
etc.
saving_id = 2, cost = 110, savings = 10, age = 27
saving_id = 2, cost = 110, savings = 10, age = 28
etc.

Существует ли какой-либо встроенный механизм для выравнивания списка таким образом, и / или кто-нибудь знает, как этого добиться? Заранее спасибо,

*

JP 1017 *

Ответы [ 2 ]

8 голосов
/ 25 октября 2010

Вы можете использовать Seq.collect.Он объединяет последовательности вместе, так что в вашем случае вы можете сопоставить функцию с вашим вводом, которая разбивает одну запись возрастного диапазона на последовательность записей возраста, и использовать Seq.collect для их склеивания.

Например:

type myRecord =
{ saving_id: int;
  cost: int;
  savings: int;
  min_age: int;
  max_age: int }

type resultRecord =
    { saving_id: int;
      cost: int;
      savings: int;
      age: int }

let records = 
    [ { saving_id = 1; cost = 100; savings = 20; min_age = 20; max_age = 26 }
      { saving_id = 2; cost = 110; savings = 10; min_age = 27; max_age = 31 } ]

let splitRecord (r:myRecord) =
    seq { for ageCounter in r.min_age .. r.max_age -> 
            { saving_id = r.saving_id;
              cost = r.cost;
              savings = r.savings;
              age = ageCounter }
    }

let ageRanges = records |> Seq.collect splitRecord

Редактировать: вы также можете использовать генератор последовательностей с yield!

let thisAlsoWorks = 
    seq { for r in records do yield! splitRecord r }  
1 голос
/ 25 октября 2010

Соглашаясь с ответом cfern, но он задавался вопросом, может ли это быть полезным, если использовать другую «встроенную» функцию. Вот альтернативная версия функции splitRecord, которая показывает вызов библиотеки для развертывания последовательности. Здесь нет никакой выгоды, кроме как для примера Seq.unfold.

let splitRecord (r:myRecord) = 
    Seq.unfold (fun curr_age ->
                    if curr_age <= r.max_age then
                        Some({  saving_id = r.saving_id; 
                                cost = r.cost; 
                                savings = r.savings; 
                                age = curr_age } ,
                                curr_age + 1) 
                    else None)
                r.min_age
...