In Haskell, how do you trim whitespace from the beginning and end of a string?
Solution 1
If you have serious text processing needs then use the text
package from hackage:
> :set -XOverloadedStrings
> import Data.Text
> strip " abc "
"abc"
If you're too stubborn to use text
and don't like the inefficiency of the reverse method then perhaps (and I mean MAYBE) something like the below will be more efficient:
import Data.Char
trim xs = dropSpaceTail "" $ dropWhile isSpace xs
dropSpaceTail maybeStuff "" = ""
dropSpaceTail maybeStuff (x:xs)
| isSpace x = dropSpaceTail (x:maybeStuff) xs
| null maybeStuff = x : dropSpaceTail "" xs
| otherwise = reverse maybeStuff ++ x : dropSpaceTail "" xs
> trim " hello this \t should trim ok.. .I think .. \t "
"hello this \t should trim ok.. .I think .."
I wrote this on the assumption that the length of spaces would be minimal, so your O(n) of ++
and reverse
is of little concern. But once again I feel the need to say that if you actually are concerned about the performance then you shouldn't be using String
at all - move to Text
.
EDIT making my point, a quick Criterion benchmark tells me that (for a particularly long string of words with spaces and ~200 pre and post spaces) my trim takes 1.6 ms, the trim using reverse takes 3.5ms, and Data.Text.strip
takes 0.0016 ms...
Solution 2
From: http://en.wikipedia.org/wiki/Trim_(programming)#Haskell
import Data.Char (isSpace)
trim :: String -> String
trim = f . f
where f = reverse . dropWhile isSpace
Solution 3
After this question was asked (circa 2012) Data.List
got dropWhileEnd
making this a lot easier:
trim = dropWhileEnd isSpace . dropWhile isSpace
Solution 4
Inefficient but easy to understand and paste in where needed:
strip = lstrip . rstrip
lstrip = dropWhile (`elem` " \t")
rstrip = reverse . lstrip . reverse
Solution 5
Nowadays the MissingH
package ships with a strip
function:
import Data.String.Utils
myString = " foo bar "
-- strip :: String -> String
myTrimmedString = strip myString
-- myTrimmedString == "foo bar"
So if the conversion from String
to Text
and back does not make sense in your situation, you could use the function above.
Eric Normand
Updated on July 05, 2022Comments
-
Eric Normand almost 2 years
How do you trim whitespace from the start and end of a string?
trim " abc " => "abc"
Edit:
Ok, let me be a little clearer. I did not understand that string literals were treated so differently from Strings.
I would like to do this:
import qualified Data.Text as T let s :: String = " abc " in T.strip s
Is this possible in Haskell? I am using -XOverloadedStrings but that appears only to work for literals.