如何编写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.
相关产品推荐
相关产品推荐

