Haskell如何更新元组列表[(String,Int)]指定元素且保留完整结构?
Haskell列表更新逻辑修正方案
问题根因
你的代码没有保留匹配到目标字符串前的遍历元素,otherwise分支直接返回递归调用的结果,直接丢弃了当前不匹配的元素,导致最终结果只剩下匹配项及其后续的列表内容。
修正代码
写法1(借助fmap,更简洁)
myFunc :: String -> [(String, Int)] -> Maybe [(String, Int)] myFunc s [] = Nothing myFunc s ((s2,i):xs) | s == s2 = Just ((s2, i - 1) : xs) | otherwise = fmap ((s2,i) :) (myFunc s xs)
写法2(case分支,更易读)
myFunc :: String -> [(String, Int)] -> Maybe [(String, Int)] myFunc s [] = Nothing myFunc s ((s2,i):xs) | s == s2 = Just ((s2, i - 1) : xs) | otherwise = case myFunc s xs of Just modifiedTail -> Just ((s2,i) : modifiedTail) Nothing -> Nothing
逻辑说明
- 匹配到目标字符串时,逻辑和原来一致,返回修改后的当前元素加后续列表的
Just包装值 - 未匹配到目标字符串时,先递归处理后续列表:
- 如果递归返回修改完成的后半段列表,就把当前不匹配的元素拼接到后半段头部,保留前面的所有元素
- 如果递归返回
Nothing(说明后续列表也没有目标元素),就整体返回Nothing
用你给出的测试用例调用myFunc "l2" [("l1",10), ("l2",20), ("l3",30)],最终会返回Just [("l1",10),("l2",19),("l3",30)],符合预期。
内容的提问来源于stack exchange,提问作者Guilherme Silva Souza
相关产品推荐
相关产品推荐

