Haskell程序在字符串中查找子字符串

时间:2014-07-23 11:10:09

标签: string haskell maybe

我想用这种类型的签名编写一个Haskell函数:

findStr :: String -> String -> Maybe Int

findStr pat str会尝试在字符串pat中找到子字符串str。如果成功,它将返回Just n,其中npat内的位置为str

Example:

findStr "abc" "abcdefg" -- returns Just 0

3 个答案:

答案 0 :(得分:1)

试试这个:

findStr :: String -> String -> Maybe Int
findStr pat str = findStrHelp pat str 0
  where
    findStrHelp _ [] _ = Nothing
    findStrHelp pat s@(x:xs) n
      | pat == (take (length pat) s) = Just n
      | otherwise = findStrHelp pat xs (n+1)

findStr调用辅助函数来跟踪当前索引。 findStrHelp然后只需要检查输入的模式是否等于模式长度的下一个子串。如果是,则返回Just <index>,否则检查下一个子字符串。如果遇到空列表,则会失败并返回Nothing

答案 1 :(得分:1)

这是另一个解决方案,也使用递归:

findStr :: String -> String -> Maybe Int
findStr sub s
          | length sub > length s      = Nothing
          | take (length sub) s == sub = Just 0
          | otherwise                  = fmap (+1) $ findStr sub $ drop 1 s

有两个终止条件:子字符串大于字符串,在这种情况下返回Nothing(我们停止递归)或子字符串匹配字符串的开头,在这种情况下我们停止递归因为我们有匹配(我们返回Just 0)。

如果没有达到终止条件,我们会计算我们所处的位置,并通过删除字符串的第一个字符来递减。

答案 2 :(得分:0)

试试这个:

findStr :: String -> String -> Maybe Int
findStr x y
           | (length $ filtered x y) == 0 = Nothing
           | otherwise = Just $ fst $ head $ filtered x y

filtered :: String -> String -> [(Int, String)]
filtered x y = filter (\(p,q) -> q == x) $ zip [0..(1 + lenY - lenX)] [take lenX $ drop n y | n <- [0..(lenY - lenX)]]
                where lenX = length x
                      lenY = length y

filtered是一个帮助函数,它使用zip来创建索引的键值对列表以及长度等于pat的子串的相应子串,然后获取匹配{{}的那些对。 1}}。如果以上列表为空,即未找到匹配项,则pat会返回findStr,或Nothing其中k是第一个匹配索引。