我是F#的新手,我想知道如何对列表进行扁平化。
基本上在数据库中我存储了一个min_age和max_age范围的记录(为了简洁起见,这是一个虚构的例子 - 我并不痛苦!)。我的字段如下所示:
ID, 成本, 储蓄, 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
答案 0 :(得分:8)
您可能想要使用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 :(得分:1)
同意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