2012-07-11 105 views
2

我目前正在嘗試查找另一個字符串中特定字符串的索引。 因此,例如在"ababa baab ab bla ab"結果字符串"ab"應該是11和18 如果當前有問題,與我的功能我也得到該指數在0和8
我的功能:Haskell查找字符串中字符串的索引

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

你應該得到的第一個索引,給您的規格,爲0 – 2012-07-11 12:21:14

+0

@larsmanns你說得對,我編輯我的問題 – LeonS 2012-07-11 12:22:35

+3

所以你實際上是尋找字符串「ab」,而不是「ab」。注意空間 – Squidly 2012-07-11 12:22:50

回答

6

挑選合適的設備在這裏很重要。

import Data.Char 

你可以從你的序幕,這被定義爲使用該功能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] 
0
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] 

這可以通過使用(++)代替的利弊((:))是固定的。

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] 
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"