split elements into groups haskell

拈花ヽ惹草 提交于 2019-12-24 16:53:25

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!