在两个元素对中搜索字符串

时间:2013-12-14 16:38:43

标签: haskell

我再次陷入困境 我有一对字符串[(String, String)]的列表,并希望在其中查找另一个字符串。 当子串与元组中的第一个匹配时,我想返回第二个,反之亦然。

我有一些想法但又一次,我不知道如何在Haskell中正确应用函数。 我的第一个想法是使用map,但结果却无法给我一个字符串,是吗?

我在考虑使用filter。首先搜索对中第一个中的子串,然后搜索第二个中的子串 这是我得到的:

search :: String -> [(String, String)] -> String
search substr xs = filter(==substr) xs.fst

它甚至不起作用:/

我会感谢任何建议!

由于

3 个答案:

答案 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