问题
Hey Im new to functional programming and learning haskell.
I'm wondering whether will i be able to split elements in a list and grouping them in two's.
I already saw the splitAt
operations and it only splits at specified index value/ position
splitAt 3 [1,2,3,4,5] -> [1,2,3][4,5]
Now I'm wondering say I have a list where random characters [A,S,D,F,G,H,J,K,U,Y,R,E,W,V,B,N]
,
I want to split this as [A,S][D,F][G,H][J,K].... and so on
..
I' m totally stuck up in this ! Please help me out !
回答1:
You can write a function for that yourself:
mySplit :: Int -> [a] -> [[a]]
mySplit n [] = []
mySplit n xs = (take n xs):(mySplit n (drop n xs))
Demo:
λ> mySplit 2 [1,2,3,4,5,6]
[[1,2],[3,4],[5,6]]
λ> mySplit 2 [1,2,3,4,5,6,7]
[[1,2],[3,4],[5,6],[7]]
Another way would be to use the split package:
λ splitEvery 3 ['a'..'z']
["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"]
回答2:
First when asking such a question, specify the type signature you want! So you want to create (given a constant sublist-length) from a flat list a whole list of lists. That suggests the signature
splitOfLen :: Int -> [a] -> [[a]]
Before you start implementing, it's clever to see if anybody has done that before:
- Hoogle gives a whole lot of similar result, but none that really matches.
- Hayoo shows that the function has been implemented in a whole lot of libraries, but really just as a local helper.
If you want to do it yourself, you should start with splitAt
(which splits off one prefix) and progress to do that while anything remains:
splitsOfLen l xs = case splitAt l xs of
(p, []) -> [p]
(p, r) -> p : splitsOfLen l r
回答3:
You can also continue to use splitAt
, you just have to recurse over it manually:
chunks :: Int -> [a] -> [[a]]
chunks n [] = []
chunks n xs = head : (chunks n tail)
where (head, tail) = splitAt n xs
λ> chunks 2 [1,2,3,4,5])
[[1,2],[3,4],[5]]
I thought this might be more efficient (avoiding the need to evaluate take
and drop
explicitly), but according to the documentation for Data.List:
It is equivalent to
(take n xs, drop n xs)
when n is not_|_
(splitAt _|_ xs = _|_
).
I guess there's always more than one way to do it! It is interesting to see how each answer uses a different method of pattern-matching.
回答4:
There is a great function in Data.Lists.Split named chunksOf
that with the parameter 2 wiLL pull pairs out of a list. chunksOf
will pull the last odd element out of the list. Say given 3 elements, it will produce 2 and 1 element(s) in lists.
The following pairing function also pullS the last straggler from the list.
pairs = takeWhile (not.null) . map (take 2) . iterate (drop 2)
I think the following is better. It is set up for pairs but can be parameterized to do any size chunk. It will take any list and include single elements.
np ls = [take 2 (drop a ls)|a<-[0,2..(length ls)-1]]
来源:https://stackoverflow.com/questions/25617970/split-elements-into-groups-haskell