2010-10-25 109 views
3

我是F#的新手,想知道如何去平展列表。F# - 展平列表/範圍

基本上在數據庫中,我存儲了一個min_age和max_age範圍的記錄(爲了簡潔起見,這是一個虛構的例子 - 我不是agist!)。我的字段類似如下:

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

回答

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 

編輯:您還可以使用序列發生器的產量!

let thisAlsoWorks = 
    seq { for r in records do yield! splitRecord r } 
+0

尼斯的答案。我想在OP要求一個「內置的機制」,如果有不涉及任何自定義記錄類型,將真的只是工作,但因爲它是這個解決方案看起來優雅的,因爲它得到。 – 2010-10-25 10:35:44

+0

序列表達式可以是一個通用的優雅的一行:'讓壓扁seqOfSeq = SEQ {用於seqOfSeq不產生SEQ! SEQ}'。 – MasterMastic 2014-02-09 03:08:42

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 
+0

有趣的解決方案:)當然我覺得在幾乎所有情況下,'而無論做產生value'幾乎總是比Seq.unfold :) – Juliet 2010-10-25 13:39:27

+0

更具可讀性@Juliet我發現,想看看圖書館功能的情況比比皆是幫助記住他們他們應該變得有用。 :) – 2010-10-25 13:47:54