代码之家  ›  专栏  ›  技术社区  ›  JP.

f-展平列表/范围

  •  3
  • JP.  · 技术社区  · 14 年前

    我对f不太熟悉,我想知道我该怎么做才能把一个列表拉平。

    基本上,在数据库中,我存储了一个最小年龄和最大年龄范围的记录(为了简洁起见,这是一个虚构的例子——我不敏捷!).My字段如下所示:

    身份证件, 成本, 储蓄, 最小年龄, 最大年龄

    本质上,我有一个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.
    

    是否有任何内置机制以这种方式扁平列表和/或有人知道如何实现这一点? 事先谢谢,

    日本药典

    2 回复  |  直到 14 年前
        1
  •  8
  •   cfern    14 年前

    您可能需要使用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
    

    编辑:你也可以使用一个序列发生器与产量!

    let thisAlsoWorks = 
        seq { for r in records do yield! splitRecord r }  
    
        2
  •  1
  •   Alexander Rautenberg    14 年前

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