在Haskell中第n个字符出现后删除每个字符

时间:2016-10-28 15:48:58

标签: string haskell

对于字符串str,如何在n出现c字符后删除每个字符?

例如,如果str"2016-10-20",那么如何在第二次出现字符-后删除每个字符,产生"2016-10"

3 个答案:

答案 0 :(得分:3)

标准库中没有方便的split功能,因此您必须自己滚动。一种方法:

dropAfter :: Int -> Char -> String -> String

dropAfter _ _ "" = ""
dropAfter 0 d (x:xs) = ""
dropAfter 1 d (x:xs) | x == d = ""
dropAfter n d (x:xs) | x == d = x : dropAfter (n-1) d xs
                     | otherwise = x : dropAfter n d xs

split包确实提供了splitOn :: Eq a => [a] -> [a] -> [[a]]

import Data.List.Split (splitOn)
import Data.List (intercalate)
dropAfter n d = intercalate [d] . take n . splitOn [d]

答案 1 :(得分:3)

折叠的恶魔再次袭来。

dropAfter :: Int -> (a -> Bool) -> [a] -> [a]
dropAfter n _ _ | n < 1 = []
dropAfter n f xs = foldr go (`seq` []) xs n where
  go x r !k
    | f x = if k == 1 then [] else x : r (k - 1)
    | otherwise = x : r k

答案 2 :(得分:1)

或者,您可以使用它作为开始使用解析器的垫脚:

λ import Text.Parsec
λ runParser (many (noneOf "-") `sepBy` char '-') () "example from question" "2016-01-43"
Right ["2016","01","43"]
λ import Data.List
λ intercalate "-" . take 2 <$> it
Right "2016-01"

现在进行切换的好处在于,随着您对输入的更多了解(以及它能够和不可能看起来如何),更新解析器以进行匹配相当容易,使用自定义函数可以真正快速变得真实。