【问题标题】:Haskell find indices of String in StringHaskell 在 String 中查找 String 的索引
【发布时间】:2012-07-11 12:18:37
【问题描述】:

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

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

【问题讨论】:

  • 根据您的规范,您应该得到的第一个索引是 0。
  • @larsmanns 你说得对,我编辑了我的问题
  • 所以您实际上是在寻找字符串“ab”,而不是“ab”。注意空格
  • 另外,你得了 2。我猜你对单词提取很感兴趣?
  • 请相应地改写问题并给出输入和期望输出的例子。

标签: string haskell find substring


【解决方案1】:

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

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]

【讨论】:

    【解决方案2】:
    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]
    

    【讨论】:

      【解决方案3】:

      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"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-07
        • 2014-07-24
        • 2018-03-04
        • 1970-01-01
        • 1970-01-01
        • 2015-05-26
        • 1970-01-01
        • 2015-04-18
        相关资源
        最近更新 更多