我想用这种类型的签名编写一个Haskell函数:
findStr :: String -> String -> Maybe Int
findStr pat str
会尝试在字符串pat
中找到子字符串str
。如果成功,它将返回Just n
,其中n
在pat
内的位置为str
。
Example:
findStr "abc" "abcdefg" -- returns Just 0
答案 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是第一个匹配索引。