Reputation: 671
Im trying to write a function that takes in a string and then returns the string as a list of string-words (like the words built-in function) and so far i've written
ord :: String -> [String]
ord [] = []
ord xs = let
ys = groupBy (\x y -> y /= ' ') xs
in filter (not . null) ys
I thougth this would get rid of the empty strings from the list but i only get this output
input:
ord “aa b c - dd”
output:
["aa"," b"," "," "," "," "," "," "," c"," "," "," -"," "," "," "," dd"]
when this is the output i want:
[“aa”, ”b”, ”c”, ”-“, ”dd”]
I get the same result if i try and write
ord :: String -> [String]
ord [] = []
ord xs = filter (not . null) ys
where
ys = groupBy (\x y -> y /= ' ') xs
How do i re-write this code so that i rid the list of its empty strings? Or use the proper syntax? Im just learning Haskell and im still having trouble with the syntax...
Upvotes: 2
Views: 193
Reputation: 48581
I wouldn't bother with groupBy
at all here. In particular, there's no need to build lists of spaces just to throw them away. Let's start with a function that drops initial spaces and then grabs everything to the first space:
grab :: String -> (String, String)
grab = break isSpace . dropWhile isSpace
Note that the first component of grab xs
will be empty if and only if all the elements of xs
are spaces.
Now we can write
myWords :: String -> [String]
myWords xs = case grab xs of
([], _) -> []
(beginning, end) -> beginning : myWords end
Upvotes: 3
Reputation: 476557
groupBy
means that you put x
and y
in the same group, given the condition is satisfied. But here you group the two together, given y
is not equal to a space.
You thus can alter your grouping predicate, and put x
and y
in the same group, given both are spaces, or non-spaces:
import Data.Char(isSpace)
ord :: String -> [String]
ord [] = []
ord xs = let
ys = groupBy (\x y -> isSpace x == isSpace y) xs
in filter (not . null) ys
or shorter:
import Data.Char(isSpace)
import Data.Function(on)
ord :: String -> [String]
ord [] = []
ord xs = let
ys = groupBy (on (==) isSpace) xs
in filter (not . null) ys
Now we retrieve:
Prelude Data.List> ord "aa b c - dd"
["aa"," ","b"," ","c"," ","-"," ","dd"]
We of course still not obtain the expected result. In stead of filtering out empty strings, we can filter out strings that only contain spacing characters:
import Data.Char(isSpace)
import Data.Function(on)
ord :: String -> [String]
ord [] = []
ord xs = let
ys = groupBy (on (==) isSpace) xs
in filter (not . all isSpace) ys
We do not need to covert the empty case manually, since groupBy
on an empty list produces an empty list, we can thus construct a one liner to do the processing:
import Data.Char(isSpace)
import Data.Function(on)
ord :: String -> [String]
ord = filter (not . all isSpace) . groupBy (on (==) isSpace)
Then we obtain the expected result:
Prelude Data.List Data.Char> ord "aa b c - dd"
["aa","b","c","-","dd"]
Upvotes: 5