Haskell中如何融合两个Purchase中的重复Order项?
原函数的问题
- 缺少必要模块导入:
nub函数属于Data.List模块,未导入会导致编译错误(提示nub未定义),容易被误判为类型匹配错误。 - 逻辑隐患:
- 仅通过Product的ID分组,但严格来说
Product是包含ID、名称、价格的元组,若存在同ID但名称/价格不同的Product,原函数会强行合并并仅保留第一个匹配ID的Product信息,可能不符合预期。 - 使用
head处理空列表会触发运行时崩溃(理论上当前逻辑不会出现空列表,但代码存在风险)。
- 仅通过Product的ID分组,但严格来说
- 冗余计算:多次重复遍历
p1 ++ p2,效率较低。
修改方案
- 导入
Data.List(及Data.Function用于简化分组逻辑)。 - 明确分组依据:要么按完整Product元组(三个字段全相等)合并,要么按Product的ID合并(需确认业务允许忽略名称/价格差异)。
- 利用分组函数替代多次遍历,同时避免
head的潜在风险。
正确可运行函数
情况1:按完整Product合并(推荐,符合类型语义)
只有当Product的ID、名称、价格完全相同时,才合并对应Order的数量:
import Data.List (groupBy) import Data.Function (on) type Product = (Int, String, Float) type Order = (Product, Int) type Purchase = [Order] fusePurchases :: Purchase -> Purchase -> Purchase fusePurchases p1 p2 = map mergeOrders groupedOrders where allOrders = p1 ++ p2 -- 按完整Product分组 groupedOrders = groupBy ((==) `on` fst) allOrders -- 合并同组Order:取Product,求和数量 mergeOrders orders = (fst $ head orders, sum $ map snd orders)
情况2:按Product的ID合并
仅通过ID判断是否为同一Product,合并数量并保留第一个出现的Product信息:
import Data.List (nub) type Product = (Int, String, Float) type Order = (Product, Int) type Purchase = [Order] fusePurchases :: Purchase -> Purchase -> Purchase fusePurchases p1 p2 = map mergeById uniqueIds where allOrders = p1 ++ p2 uniqueIds = nub [fst prod | (prod, _) <- allOrders] -- 合并同一ID的所有Order mergeById pid = let matchingOrders = filter (\(prod, _) -> fst prod == pid) allOrders in (fst $ head matchingOrders, sum $ map snd matchingOrders)
内容的提问来源于stack exchange,提问作者Antoniou
相关产品推荐
相关产品推荐

