我需要一个函数来查找字符串中子串的所有索引。下面你可以找到我的代码,但我只是想知道是否有更好的方法:
-- 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
答案 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
获取sub
中str
的第一个字符的所有索引,然后过滤掉与sub
不对齐的索引}不是从该索引开始的前缀。这解决了查找所有索引的问题。
然后我们可以简单地将此功能用于indexOfSubStr
。我本可以把函数写成
indexOfSubStr sub str = listToMaybe $ indicesOfSubStr sub str
事实上,这个方法总共短了8个字符,但我通常已经定义了(.:)
运算符,谁不喜欢点自由?如果你对它的作用感到困惑(定义有点神秘,就像类型签名一样),它实际上只是用一个两个参数函数组成一个参数函数。