2009-11-27 80 views
13

假設我有這樣的tupples的列表:集團通過與F#元組

[("A",12); ("A",10); ("B",1); ("C",2); ("C",1)] 

,我願做某種groupby我該如何處理這個問題?

僞代碼,SQL應該是這個樣子:

SELECT fst(tpl), sum(lst(tpl)) FROM [TupplesInList] GROUP BY fst(tpl) 

產生

[("A",22); ("B",1); ("C",3)] 

我可以做一個解釋,如果該鍵存在添加的整數,但我很難相信將會是語言表達能力與F#一樣的最佳解決方案。

回答

24

一個解決方案:

let tuples = [("A",12); ("A",10); ("B",1); ("C",2); ("C",1)] 
tuples 
|> Seq.groupBy fst 
|> Seq.map (fun (key, values) -> (key, values |> Seq.sumBy snd)) 

編輯: ...或無管道:

let tuples = [("A",12); ("A",10); ("B",1); ("C",2); ("C",1)] 
Seq.map (fun (key, group) -> key, Seq.sumBy snd group) 
     (Seq.groupBy fst tuples) 
14

爲了擴大對約翰的回答,我傾向於做很多這種事情,因此取得了下面的泛化函數。

let group_fold key value fold acc seq = 
    seq |> Seq.groupBy key 
     |> Seq.map (fun (key, seq) -> (key, seq |> Seq.map value |> Seq.fold fold acc)) 

所看到如下

let tuples = [("A",12); ("A",10); ("B",1); ("C",2); ("C",1)] 

let regular = group_fold fst snd (+) 0 tuples 
let piped = tuples |> group_fold fst snd (+) 0 

也將與其他seqences工作就像一個字符串列表,爲您的元組的情況下,其中一期工程

let strings = ["A12"; "A10"; "B1"; "C2"; "C1"] 

let regular = group_fold (fun (x : string) -> x.[0]) (fun (x : string) -> int x.[1..]) (+) 0 strings 
let piped = strings |> group_fold (fun x -> x.[0]) (fun x -> int x.[1..]) (+) 0