Created
September 14, 2012 16:00
-
-
Save ruthenium/3722863 to your computer and use it in GitHub Desktop.
Split string by predicate including the matched element.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
----------------------------------------------------------------------------- | |
{-| Split a 'String', by specified predicate, but do not remove matched | |
characters from the result. | |
Not an efficient implementation. | |
First, it folds a 'String' to a list of Strings. | |
Elements in the resulting list are in the reversed order, because they | |
are prepended to the final list, not appended. | |
At the end, it reverses the result. | |
-} | |
splitROne :: (Char -> Bool) -> String -> [String] | |
splitROne p = reverse . foldl (part) [] | |
where | |
-- partition function | |
part :: [String] -> Char -> [String] | |
part [] c = [ [c] ] -- first letter | |
part lst@(x:xs) c | p c = [c]:lst -- predicate matches on letter, create new group | |
| otherwise = (x ++ [c]) : xs -- ordinary letter, add it to first group | |
----------------------------------------------------------------------------- | |
----------------------------------------------------------------------------- | |
{-| Split a 'String' by specified predicate, but do not remove matched | |
characters from the result. | |
Efficient recursive implementation inspired by the "Real World Haskell" | |
book. | |
NOTE: | |
This implementation may cause an empty first element of a result, | |
because the behaviour of the 'break' function. | |
-} | |
splitRTwo :: (Char -> Bool) -> String -> [String] | |
splitRTwo p s = | |
let (b, r) = break p s | |
in b : case r of | |
[] -> [] | |
(h:t) -> (h : hs) : ts | |
where | |
(hs:ts) = splitRTwo p t | |
----------------------------------------------------------------------------- | |
----------------------------------------------------------------------------- | |
{-| Split a 'String' by specified predicate, but do not remove matched | |
characters from the result. | |
Efficient recursive implementation inspired by the "Real World Haskell" | |
book. The same as above, but implemented another way, | |
using case and where. | |
NOTE: | |
This implementation may cause an empty first element of a result, | |
because the behaviour of the 'break' function. | |
-} | |
splitRThree :: (Char -> Bool) -> String -> [String] | |
splitRThree p s = case break p s of | |
(b, []) -> [ b ] | |
(b, (h:t)) -> b : (h : hs) : ts | |
where | |
(hs:ts) = splitRThree p t | |
----------------------------------------------------------------------------- | |
----------------------------------------------------------------------------- | |
{-| Split a 'String' by specified predicate, but do not remove matched | |
characters from the result. | |
Recursive implementation inspired by the "Real World Haskell" book. | |
This implementation variant holds the first and the rest matches | |
separately. | |
The inner local function 'go' accepts a previously matched character | |
and joins it with the result, so extra splitting it is not needed. | |
The algorithm is similar to the functions above. | |
-} | |
splitRFour :: (Char -> Bool) -> String -> [String] | |
splitRFour _ [] = [] | |
splitRFour p s = case break p s of | |
(b, []) -> [ b ] -- no characters matching predicate in the string | |
([], (h:t)) -> go h t -- first character of the string matches predicate | |
(b, (h:t)) -> b : go h t | |
where | |
go :: Char -> String -> [String] | |
go m s' = case break p s' of | |
(b', []) -> [ m:b' ] | |
(b', (x:xs)) -> (m : b') : go x xs | |
----------------------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment