You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写Elm函数实现对记录列表按last分组并求和age?

Hey there! 要在Elm里实现类似SQL的GROUP BY聚合操作其实很直观,咱们可以用核心库的Dict模块来处理分组,再结合列表折叠(fold)来完成求和计算。我直接给你上代码和解释:

第一步:定义数据类型

因为Elm是强类型语言,先明确输入和输出的数据结构:

-- 输入的人员数据类型
type alias Person =
    { name : String
    , last : String
    , age : Int
    }

-- 分组后的结果类型
type alias GroupedAgeSum =
    { last : String
    , age : Int
    }

第二步:实现分组求和函数

这里我们用List.foldl遍历列表,同时用Dict维护每个姓氏对应的年龄总和,最后转换为目标格式:

groupByLastAndSumAge : List Person -> List GroupedAgeSum
groupByLastAndSumAge people =
    people
        -- 第一步:遍历列表,用Dict记录每个last对应的年龄总和
        |> List.foldl
            (\person ageDict ->
                Dict.update
                    person.last
                    (\maybeTotal ->
                        -- 如果该姓氏已有记录,就累加年龄;没有的话就初始化为当前年龄
                        case maybeTotal of
                            Just total -> Just (total + person.age)
                            Nothing -> Just person.age
                    )
                    ageDict
            )
            Dict.empty  -- 初始化为空字典
        -- 第二步:把字典转成键值对列表,再映射成我们要的结果格式
        |> Dict.toList
        |> List.map (\(lastName, totalAge) -> { last = lastName, age = totalAge })

测试示例

用你给出的输入来验证:

sampleInput : List Person
sampleInput =
    [ { name = "John", last = "Smith", age = 10 }
    , { name = "Jason", last = "Smith", age = 9 }
    , { name = "Jane", last = "White", age = 5 }
    ]

-- 调用函数后得到的结果就是你想要的:
-- [{last = "Smith", age = 19}, {last = "White", age = 5}]
result = groupByLastAndSumAge sampleInput

额外的通用版本(可选)

如果以后需要更灵活的分组聚合(比如按不同字段分组、做取最大值/最小值等操作),可以封装一个通用函数:

-- 通用分组聚合函数:指定分组键提取函数和聚合函数
groupBy : (a -> comparable) -> (List a -> b) -> List a -> List (comparable, b)
groupBy getKey aggregate list =
    list
        |> List.foldl
            (\item dict ->
                Dict.update
                    (getKey item)
                    (\maybeItems ->
                        case maybeItems of
                            Just items -> Just (item :: items)
                            Nothing -> Just [item]
                    )
                    dict
            )
            Dict.empty
        |> Dict.toList
        |> List.map (\(key, items) -> (key, aggregate items))

-- 用通用函数实现你的需求
groupByLastAndSumAge' : List Person -> List GroupedAgeSum
groupByLastAndSumAge' people =
    people
        |> groupBy .last (List.sum << List.map .age)
        |> List.map (\(last, total) -> { last = last, age = total })

这个版本先收集同组的所有数据,再用你指定的聚合函数处理,适合需要对组内数据做更多操作的场景。

内容的提问来源于stack exchange,提问作者Jason O.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:34:13