所有出现在字符串中的子串

时间:2013-11-02 18:13:20

标签: haskell

我需要一个函数来查找字符串中子串的所有索引。下面你可以找到我的代码,但我只是想知道是否有更好的方法:

-- find index of substring in string
--      index_of_substring "so" "unsomesome" -> Just 2
--      index_of_substring "to" "unsomesome" -> Nothing
index_of_substring :: String -> String -> Maybe Int
index_of_substring _ []  = Nothing
index_of_substring sub str = case List.isPrefixOf sub str of
    False -> fmap (+1) $ index_of_substring sub (tail str)
    True  -> Just 0

-- find all occurences of pattern in a string
--      all_occurrences_of_pattern_in_string "so" "unsomesomesome" -> [2,6,10]
all_occurrences_of_pattern_in_string pattern s = helper pattern s [] 0
    where helper pattern s result last_idx = case index_of_substring pattern s of
            Just n -> helper pattern (drop (n + 1) s) (result ++ [n + last_idx]) (last_idx + n + 1)
            Nothing -> result

1 个答案:

答案 0 :(得分:0)

我想说至少可以做得更简单。除非重点是从头开始编写自己的算法(因为你使用Data.List.isPrefixOf我不认为是这种情况),你可以简单地利用Data.List.elemIndices来缩短你的支票数量要做:

indicesOfSubStr :: String -> String -> [Int]
indicesOfSubStr []  _   = []
indicesOfSubStr sub str = filter (\i -> sub `isPrefixOf` drop i str) $ head sub `elemIndices` str

indexOfSubStr :: String -> String -> Maybe Int
indexOfSubStr = listToMaybe .: indicesOfSubStr where (.:) = (.) . (.)

所以在这里我使用elemIndices获取substr的第一个字符的所有索引,然后过滤掉与sub不对齐的索引}不是从该索引开始的前缀。这解决了查找所有索引的问题。

然后我们可以简单地将此功能用于indexOfSubStr。我本可以把函数写成

indexOfSubStr sub str = listToMaybe $ indicesOfSubStr sub str

事实上,这个方法总共短了8个字符,但我通常已经定义了(.:)运算符,谁不喜欢点自由?如果你对它的作用感到困惑(定义有点神秘,就像类型签名一样),它实际上只是用一个两个参数函数组成一个参数函数。