2

我目前正在尝试在另一个字符串中查找特定字符串的索引。因此,例如字符串"ab"in的结果"ababa baab ab bla ab"应该是 11 和 18。如果当前有问题,我的函数也得到索引 0 和 8
我的函数:

findSubstringIndices :: String -> String -> [Int]
findSubstringIndices text pattern = map (add 1) (findIndices (pattern `isPrefixOf`) (tails text))
4

3 回答 3

6

在这里选择合适的设备很重要。

import Data.Char

您可以使用 Prelude 中函数的略微修改版本words,其定义为:

words :: String -> [String]
words s = case dropWhile isSpace s of
  "" -> []
  s' -> w : words s'' where (w, s'') = break isSpace s'

它将字符串分解为以空格分隔的单词列表。修改相当于用字符串中的索引标记每个单词。例如:

words' :: String -> [(Int, String)]
words' = go 0
  where
    go n s = case break (not . isSpace) s of
      (_, "")  -> []
      (ws, s') -> (n', w) : go (n' + length w) s''
                     where
                       n'       = n + length ws
                       (w, s'') = break isSpace s'

例如:

> words' "ababa baab ab bla ab"
[(0,"ababa"),(6,"baab"),(11,"ab"),(14,"bla"),(18,"ab")]

现在,编写你的函数findSubstringIndices变得几乎是微不足道的:

findSubstringIndices :: String -> String -> [Int]
findSubstringIndices text pattern = [i | (i, w) <- words' text, w == pattern]

它有效吗?是的,它确实:

> findSubstringIndices "ababa baab ab bla ab" "ab"
[11,18]
于 2012-07-11T13:04:00.227 回答
1
findWordIndices' :: String -> String -> [Int]
findWordIndices' w = snd . foldl doStuff (0, []) . words
  where
    doStuff (cur, results) word =
        if word == w 
        then (cur + length word + 1, cur : results) 
        else (cur + length word + 1, results)  

但是,这会以相反的顺序返回索引。

g>let str = "ababa baab ab bla ab"
str :: [Char]
g>findWordIndices' "ab" str
[18,11]
it :: [Int]

这可以通过使用(++)代替 cons ( (:)) 来解决。

findWordIndices'' :: String -> String -> [Int]
findWordIndices'' w = snd . foldl doStuff (0, []) . words
  where
    doStuff (cur, results) word =
        if word == w 
        then (cur + length word + 1, results ++ [cur]) 
        else (cur + length word + 1, results)

g>let str = "ababa baab ab bla ab"
str :: [Char]
g>findWordIndices'' "ab" str
[11,18]
it :: [Int]
于 2012-07-11T15:59:21.853 回答
0

的另一种变体words

import Data.Char
import Control.Arrow

words' s = 
  case dropWhile isSpace' s of
    [] -> []
    s' -> ((head >>> snd) &&& map fst) w : words' s'' 
          where (w, s'') = break isSpace' s'
  where isSpace' = fst >>> isSpace

indices text pattern =
  map fst $ filter (snd >>> ((==) pattern)) $ words' $ zip text [0..]

main = do
  putStrLn $ show $ indices "ababa baab ab bla ab" "ab"
于 2012-07-11T16:00:29.133 回答