代码之家  ›  专栏  ›  技术社区  ›  Peter Booster

按F中的元组分组#

f#
  •  14
  • Peter Booster  · 技术社区  · 15 年前

    假设我有一个这样的元组列表:

    [("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这样富有表现力的语言的最佳解决方案。

    2 回复  |  直到 7 年前
        1
  •  27
  •   Johan Kullbom    15 年前

    一种解决方案:

    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)
    
        2
  •  16
  •   Joshua    15 年前

    为了扩展Johan的答案,我倾向于做这类事情,所以做了下面的广义函数。

    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))
    

    它适用于您的tuple case,如下所示

    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
    

    但也可以与其他seqence一起使用,比如字符串列表

    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