如何在Haskell的三元素元组列表中实现查找与数值修改?
解决方案
先看你的recordSale函数,目标是根据名和姓查找对应的销售数值。你之前的代码存在语法错误和逻辑问题,正确实现如下:
import Data.List (find) type Sales = (String, String, Integer) testData :: [Sales] testData = [("Jack", "Hill", 2), ("Susan", "Smith", 5), ("Steve", "Johnson", 6)] recordSale :: [Sales] -> String -> String -> Maybe Integer recordSale tData fname lname = case find (\(f, l, s) -> f == fname && l == lname) tData of Just (_, _, s) -> Just s Nothing -> Nothing
说明
- 用
find遍历列表,通过三元组模式匹配取出名、姓、数值,判断是否与传入参数匹配 find返回Maybe Sales,通过case处理两种情况:找到则返回包裹数值的Just,未找到返回Nothing(这种方式更安全,避免无匹配时的运行时错误)- 若确定输入姓名一定存在,也可使用
fromJust直接提取,但不推荐
接下来是addSale函数,需要找到对应姓名的记录并将数值加1,其他记录保持不变:
addSale :: [Sales] -> String -> String -> [Sales] addSale tData fname lname = map updateRecord tData where updateRecord (f, l, s) | f == fname && l == lname = (f, l, s + 1) | otherwise = (f, l, s)
也可以用列表推导式实现:
addSale :: [Sales] -> String -> String -> [Sales] addSale tData fname lname = [ if f == fname && l == lname then (f, l, s+1) else (f, l, s) | (f, l, s) <- tData ]
说明
- 遍历整个列表,对每个三元组做判断:匹配姓名则数值加1,否则保留原记录
- Haskell是纯函数式语言,数据不可变,因此该函数返回新的更新后列表,不会修改原列表
测试示例
main = do print $ recordSale testData "Jack" "Hill" -- 输出 Just 2 print $ recordSale testData "Alice" "Brown" -- 输出 Nothing print $ addSale testData "Susan" "Smith" -- 输出 [("Jack","Hill",2),("Susan","Smith",6),("Steve","Johnson",6)]
你之前代码的问题总结
recordSale中用了与参数同名的变量做模式匹配,导致变量遮蔽无法正确匹配;同时find语法错误,缺少右括号和逻辑判断addSale的列表推导式错误地对单个数值使用map,且未区分匹配/不匹配的情况,变量名也存在冲突
内容的提问来源于stack exchange,提问作者Power7934
相关产品推荐
相关产品推荐

