Reputation: 351
I want to be able to split a string into 6 separate strings every character.
So for example IAMABADPROGRAMMER
would result in: IDA, APM, MRM, AOE, BGR, AR
Is there a haskell function to do this?
Thanks
Upvotes: 2
Views: 1720
Reputation: 4843
I was sure this could be done with list comprehensions and nothing beyond the basic functions in Prelude...
groupNth :: Int -> [a] -> [[a]]
groupNth n [] = []
groupNth n xs = take n $ [ y | y <- everyNth xs ] : groupNth n (tail xs)
where
everyNth [] = []
everyNth l@(y:ys) = y : everyNth (drop n l)
Seems to work and I think is more efficient than using transpose.
Upvotes: 2
Reputation: 54078
There isn't a function to do it already, but it can be written quite easily:
import Data.List (transpose)
chunk :: Int -> [a] -> [[a]]
chunk _ [] = []
chunk n xs = first : chunk n rest where (first, rest) = splitAt n xs
splitSkip :: Int -> [a] -> [[a]]
splitSkip n xs = transpose $ chunk n xs
main :: IO ()
main = print $ splitSkip 6 "IAMABADPROGRAMMER"
My first intuition was to generalize this to all lists, not just lists of Char
s. When you remember that the type [String]
is the same as [[Char]]
, you see that you end up with a 2D matrix of Char
s, where if you went down each column going left-to-right, you would get the original list back. Well, that's the same as transposing the matrix and going down each row top-to-bottom, which is the same as just splitting the original list into chunks of n
elements first. At this point, I had the solution, just worked backwards. I wrote a quick function to chunk a list, then used the transpose
function from Data.List
to finish it off.
Upvotes: 3