What is the best way to split a string by a delimiter functionally?

后端 未结 9 1777
死守一世寂寞
死守一世寂寞 2020-12-29 22:11

I tried to write the program in Haskell that will take a string of integer numbers delimitated by comma, convert it to list of integer numbers and increment each number by 1

相关标签:
9条回答
  • 2020-12-29 22:36

    Just for fun, here is how you could create a simple parser with Parsec:

    module Main where
    
    import Control.Applicative hiding (many)
    import Text.Parsec
    import Text.Parsec.String
    
    line :: Parser [Int]
    line = number `sepBy` (char ',' *> spaces)
    
    number = read <$> many digit
    

    One advantage is that it's easily create a parser which is flexible in what it will accept:

    *Main Text.Parsec Text.Parsec.Token> :load "/home/mikste/programming/Temp.hs"
    [1 of 1] Compiling Main             ( /home/mikste/programming/Temp.hs, interpreted )
    Ok, modules loaded: Main.
    *Main Text.Parsec Text.Parsec.Token> parse line "" "1, 2, 3"
    Right [1,2,3]
    *Main Text.Parsec Text.Parsec.Token> parse line "" "10,2703,   5, 3"
    Right [10,2703,5,3]
    *Main Text.Parsec Text.Parsec.Token> 
    
    0 讨论(0)
  • 2020-12-29 22:38

    This is a bit of a hack, but heck, it works.

    yourFunc str = map (+1) $ read ("[" ++ str ++ "]")
    

    Here is a non-hack version using unfoldr:

    import Data.List
    import Control.Arrow(second)
    
    -- break' is like break but removes the
    -- delimiter from the rest string
    break' d = second (drop 1) . break d
    
    split :: String -> Maybe (String,String)
    split [] = Nothing
    split xs = Just . break' (==',') $ xs
    
    yourFunc :: String -> [Int]
    yourFunc = map ((+1) . read) . unfoldr split
    
    0 讨论(0)
  • 2020-12-29 22:42

    This is application of HaskellElephant's answer to original question with minor changes

    splitByDelimiter :: Char -> String -> [String]
    splitByDelimiter = unfoldr . splitSingle
    
    splitSingle :: Char -> String -> Maybe (String,String)
    splitSingle _ [] = Nothing
    splitSingle delimiter xs =
      let (ys, zs) = break (== delimiter) xs in
      Just (ys, drop 1 zs)
    

    Where the function splitSingle split the list in two substrings by first delimiter.

    For example: "1,2,-5,-23,15" -> Just ("1", "2,-5,-23,15")

    0 讨论(0)
  • 2020-12-29 22:44
    splitBy del str = helper del str []   
        where 
            helper _ [] acc = let acc0 = reverse acc in [acc0] 
            helper del (x:xs) acc   
                | x==del    = let acc0 = reverse acc in acc0 : helper del xs []  
                | otherwise = let acc0 = x : acc     in helper del xs acc0 
    
    0 讨论(0)
  • 2020-12-29 22:49

    Another without imports:

    splitBy :: Char -> String -> [String]
    splitBy _ [] = []
    splitBy c s  =
      let
        i = (length . takeWhile (/= c)) s
        (as, bs) = splitAt i s
      in as : splitBy c (if bs == [] then [] else tail bs)
    
    0 讨论(0)
  • 2020-12-29 22:51
    import qualified Text.Regex as RegExp
    
    myRegexSplit :: String -> String -> [String]
    myRegexSplit regExp theString = 
      let result = RegExp.splitRegex (RegExp.mkRegex regExp) theString
      in filter (not . null) result
    
    -- using regex has the advantage of making it easy to use a regular
    -- expression instead of only normal strings as delimiters.
    
    -- the splitRegex function tends to return an array with an empty string
    -- as the last element. So the filter takes it out
    
    -- how to use in ghci to split a sentence
    let timeParts = myRegexSplit " " "I love ponies a lot"
    
    0 讨论(0)
提交回复
热议问题