F# - 展平列表/范围

发布于 2024-09-29 01:47:17 字数 726 浏览 0 评论 0原文

我是 F# 新手,想知道如何展平列表。

本质上,我在数据库中存储了一条具有 min_age 和 max_age 范围的记录(为了简洁起见,这是一个虚构的示例 - 我并不支持!)。我的字段如下所示:

id, 成本, 储蓄, 最小年龄, 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

I'm new to F# and am wondering how I would go about flattening a list.

Essentially in the database I store a record with a min_age and max_age range (this is a fictitious example for the sake of brevity - i am not agist!). My fields look something like the following:

id,
cost,
savings,
min_age,
max_age

I essentially have an F# class that acts as a one-to-one mapping with this table - i.e. all properties are mapped exactly to the database fields.

What I would like to do is flatten this range. So, instead of a list containing items like this:

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

I would like a list containing items like this:

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.

Is there any in-built mechanism to flatten a list in this manner and/or does anyone know how to achieve this?
Thanks in advance,

JP

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

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

发布评论

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

评论(2

盛夏已如深秋| 2024-10-06 01:47:17

您可能想使用 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 }  

You might want to use Seq.collect. It concatenates sequences together, so in your case, you can map a function over your input that splits a single age range record to a sequence of age records and use Seq.collect to glue them together.

For example:

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

Edit: you can also use a sequence generator with yield!

let thisAlsoWorks = 
    seq { for r in records do yield! splitRecord r }  
飘逸的'云 2024-10-06 01:47:17

同意 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

Agreeing with cfern's answer, but was wondering if this might benefit from seeing another "built-in" function used. Here's an alternative version of the splitRecord function that shows the library call for unfolding a sequence. No gain here other than having an example for 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文