F#在记录列表中查找具有相同id的记录并将其值相加

时间:2012-03-29 12:18:55

标签: list f# find

我是F#新手,我有以下起点:

type aB = { ID: int; Slide: list<string * int> }

// examples of aB's
let aB1 = { ID = 1; Slide = [("-10%",-20); ("0%",0); ("10%",20)] }
let aB2 = { ID = 2; Slide = [("-10%",6); ("0%",0); ("10%",3)] }
let correctoraB2 = {ID = 2; Slide = [("-10%", -2); ("0%", 0); ("10%", -1)]  }

// Now we bunch the aB`s in a list together 
let bunchedABRaw = [aB1; aB2; correctoraB2]

此列表现在可以变得很长,在此列表中,我现在需要首先识别具有相同ID的所有aB,然后我想将其幻灯片网络化,以便生成新列表

let bunchedABReduced = [aB1; aB2New],其中

aB2New = { ID = 2; Slide = [("-10%",4); ("0%",0); ("10%",2)] }

我正在阅读msdn上的F#库,但到目前为止我还不知道如何解决这个问题,对于代码命题会非常高兴。

非常感谢 马丁

2 个答案:

答案 0 :(得分:2)

当我有一分钟的时候,我可以通过这个工作。

这是您可以合并两个aB的幻灯片的第一部分:

// this function can merge two slides
let mergeSlides l1 l2 = 
    List.zip l1 l2
    |> List.map (fun ((a1, b1), (a2,b2)) -> (a1, b1+b2))

// see what it does
mergeSlides aB2.Slide correctoraB2.Slide

这个位将所有aB分组为相同的Id:

let grp = bunchedABRaw
|> Seq.groupBy (fun a -> a.ID)

现在我们可以使用mergeSlides作为折叠函数,我们使用具有相同Id的Ab的每个序列折叠来制作网状aB。

所以这就是整个事情:

let mergeSlides l1 l2 = 
    List.zip l1 l2
    |> List.map (fun ((a1, b1), (a2,b2)) -> (a1, b1+b2))

let net =
    bunchedABRaw
    |> Seq.groupBy (fun a -> a.ID)
    |> Seq.map (fun (i, s) -> (i, s |> Seq.map (fun a -> a.Slide))) // strip away the slides
    |> Seq.map (fun (i, s) -> (i, List.ofSeq s)) // turn seq<slide> into list<slide>
    |> Seq.map (fun (i, l) -> (i, List.fold mergeSlides l.Head l.Tail)) // so we can use HEad and Tail
    |> Seq.map (fun (i, l) -> {ID=i;Slide=l}) // and Project into aB
    |> List.ofSeq // and then List

享受!

答案 1 :(得分:0)

试试这个:

设置一个字典,其中的键将是您遇到的ID,值将是该ID的“网状”aB类型。

然后使用字典作为您的状态在列表上运行折叠*并使您在列表中折叠的功能按ID累积字典中的项目(随时“净化”它们)。

之后,您可以将所有字典的值放入返回列表中。

如果您不能随意“净化”它们,那么您可以将项目列表存储为值而不是单个“净额”值,然后在折叠结束后进行净额结算。

* fold http://msdn.microsoft.com/en-us/library/ee353894.aspx

编辑:让事情更清楚