我有这样的代码:
appd (a:e) ((c,b):bs) | a == c && bs /= [] = b:appd(a:e) bs
| a /= c && bs /= [] = appd (a:e) bs
| a /= c && bs == [] = appd e ((c,b):bs)
| otherwise = b:appd e ((c,b):bs)
它循环遍历两个列表,如[1,2,3]
和[(1,2),(6,5),(3,5)]
,并获取第一个列表的第一个元素,并将其与其他列表中每个元组的第一个元素进行比较,如果它们相等则保存第二个元素元组。它工作正常,但如果我采用第一个列表的第二个元素,比较不起作用,在这种情况下2
。
例如,如果我有[1,2,3]
和[(1,2),(6,5),(3,5)]
等列表,则函数从第一个列表中获取1
并与1
进行比较,然后与6
进行比较,然后到3
,它可以工作,但它不需要第一个列表的第二个元素 - 2
,并且不再进行比较。怎么了?
答案 0 :(得分:1)
首先,请注意您应该包含您收到的错误消息。您还应该向我们展示一些示例输出和示例输入。
无论如何:您当前的appd
无法处理空列表,因此您需要先为此添加案例:
appd _ [] = []
appd [] bs = snd <$> bs -- you can decide to use [] instead
appd (a:e) ((c,b):bs)
| a == c && bs /= [] = b:appd(a:e) bs
| a /= c && bs /= [] = appd (a:e) bs
| a /= c && bs == [] = appd e ((c,b):bs)
| otherwise = b:appd e ((c,b):bs)
现在你的功能适用于你提供的输入,但我不确定它会返回你想要的结果:
*Main> appd [1,2,3] [(1,2),(6,5),(3,5)]
[2,5,5]
此外,我已经清理了一些代码并使用显式类型签名注释了您的函数:
appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd [] bs = snd <$> bs
appd _ [] = []
appd as@(a:ass) bs@((c,b):bss)
| a == c && bss /= [] = b : appd as bss
| a /= c && bss /= [] = appd as bss
| a /= c && bss == [] = appd ass bs
| otherwise = b : appd ass bs
,您可以使用更简单的非递归实现来获得与上面相同的结果:
appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd as bs = snd <$> filter (\(a,_) -> a `elem` as) bs
或者如果你喜欢point free(a.k.a。tacit):
appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd as = (snd <$>) . filter ((`elem` as) . fst)
注意: <$>
是fmap
的别名,在列表中使用时,其行为与map
完全相同。