Is there a standard way to split a string in Haskell?
lines
and words
work great from splitting on a space or newline, but surely there is
Try this one:
import Data.List (unfoldr)
separateBy :: Eq a => a -> [a] -> [[a]]
separateBy chr = unfoldr sep where
sep [] = Nothing
sep l = Just . fmap (drop 1) . break (== chr) $ l
Only works for a single char, but should be easily extendable.
split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s
E.g.
split ';' "a;bb;ccc;;d"
> ["a","bb","ccc","","d"]
A single trailing delimiter will be dropped:
split ';' "a;bb;ccc;;d;"
> ["a","bb","ccc","","d"]
If you use Data.Text, there is splitOn:
http://hackage.haskell.org/packages/archive/text/0.11.2.0/doc/html/Data-Text.html#v:splitOn
This is built in the Haskell Platform.
So for instance:
import qualified Data.Text as T
main = print $ T.splitOn (T.pack " ") (T.pack "this is a test")
or:
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text as T
main = print $ T.splitOn " " "this is a test"
Use Data.List.Split
, which uses split
:
[me@localhost]$ ghci
Prelude> import Data.List.Split
Prelude Data.List.Split> let l = splitOn "," "1,2,3,4"
Prelude Data.List.Split> :t l
l :: [[Char]]
Prelude Data.List.Split> l
["1","2","3","4"]
Prelude Data.List.Split> let { convert :: [String] -> [Integer]; convert = map read }
Prelude Data.List.Split> let l2 = convert l
Prelude Data.List.Split> :t l2
l2 :: [Integer]
Prelude Data.List.Split> l2
[1,2,3,4]
I don’t know how to add a comment onto Steve’s answer, but I would like to recommend the
GHC libraries documentation,
and in there specifically the
Sublist functions in Data.List
Which is much better as a reference, than just reading the plain Haskell report.
Generically, a fold with a rule on when to create a new sublist to feed, should solve it too.
Example in the ghci:
> import qualified Text.Regex as R
> R.splitRegex (R.mkRegex "x") "2x3x777"
> ["2","3","777"]