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

Haskell中如何融合两个Purchase中的重复Order项?

原函数的问题
  1. 缺少必要模块导入:nub函数属于Data.List模块,未导入会导致编译错误(提示nub未定义),容易被误判为类型匹配错误。
  2. 逻辑隐患:
    • 仅通过Product的ID分组,但严格来说Product是包含ID、名称、价格的元组,若存在同ID但名称/价格不同的Product,原函数会强行合并并仅保留第一个匹配ID的Product信息,可能不符合预期。
    • 使用head处理空列表会触发运行时崩溃(理论上当前逻辑不会出现空列表,但代码存在风险)。
  3. 冗余计算:多次重复遍历p1 ++ p2,效率较低。
修改方案
  1. 导入Data.List(及Data.Function用于简化分组逻辑)。
  2. 明确分组依据:要么按完整Product元组(三个字段全相等)合并,要么按Product的ID合并(需确认业务允许忽略名称/价格差异)。
  3. 利用分组函数替代多次遍历,同时避免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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:22:42