我再次陷入困境
我有一对字符串[(String, String)]
的列表,并希望在其中查找另一个字符串。
当子串与元组中的第一个匹配时,我想返回第二个,反之亦然。
我有一些想法但又一次,我不知道如何在Haskell中正确应用函数。
我的第一个想法是使用map
,但结果却无法给我一个字符串,是吗?
我在考虑使用filter
。首先搜索对中第一个中的子串,然后搜索第二个中的子串
这是我得到的:
search :: String -> [(String, String)] -> String
search substr xs = filter(==substr) xs.fst
它甚至不起作用:/
我会感谢任何建议!
由于
答案 0 :(得分:4)
我建议你在Maybe
中包装返回类型,以防找不到子字符串。
search :: Eq a => a -> [(a, a)] -> Maybe a
search s xs = case lookup s xs of
Just x -> Just x
Nothing -> lookup s xs'
where xs' = map swap xs
如果您不想用Maybe
包装它,只需使用fromJust
函数并相应地更改类型签名。在上面的代码中,您使用的是库定义的lookup
函数。如果在第一次搜索中查找失败,则交换元组并再次执行lookup
操作。此外,请不要忘记从swap
导入Data.Tuple
。
ghci中的演示:
ghci > let a = [("hi","bye"),("cat", "dog")]
ghci > search "hi" a
Just "bye"
ghci > search "dog" a
Just "cat"
答案 1 :(得分:3)
您可以在列表中调用lookup
,然后在交换列表中的每个元组后调用查找。但这意味着可能会两次遍历列表。
lookup' k = foldl acc Nothing
where
acc (Just x) _ = Just x
acc _ (a,b) | k == b = Just a | k == a = Just b | otherwise = Nothing
这样您只能遍历列表一次。如果元素存在,则此版本不会在无限列表上终止。您可以使用foldr编写它,但对于该版本,lookup' 0 [(0,1), undefined] == undefined
而不是首选行为。
您也可以使用显式递归来编写它。一次,使用显式递归更好!它涵盖了上述两种情况:
lookup'' k [] = Nothing
lookup'' k ((a,b):xs)
| k == a = Just b
| k == b = Just a
| otherwise = lookup'' k xs
>lookup'' 1 [(1,0), undefined]
Just 0
>lookup'' 1 (zip [0..] [0..])
Just 1
答案 2 :(得分:1)
user2407038的解决方案,lookup''
是最有效的,因为它只遍历列表一次,并在找到匹配时提前终止。它可以在没有显式递归的情况下编写,如下所示:
import Control.Monad ( msum )
lookup'' k = msum . map match
where match (a, b) | k == a = Just b
| k == b = Just a
| otherwise = Nothing