2011-12-30 43 views
12

如何在haskell中将列表分组为一个长度相等(除最后一个子列表之外)的较小列表?在haskell中细分列表

E.g.

sublist 3 [1,2,3,4,5,6,7,8] -> [[1,2,3],[4,5,6],[7,8]] 
sublist 2 [4,1,6,1,7,3,5,3] -> [[4,1],[6,1],[7,3],[5,3]] 

回答

9

如果你想坚持的前奏,你可以使用splitAt拉这一关。

splitEvery _ [] = [] 
splitEvery n list = first : (splitEvery n rest) 
    where 
    (first,rest) = splitAt n list 
+1

甚至'splitEvery N = takeWhile(不为空)。 unfoldr(Just。splitAt n)' – newacct 2011-12-31 11:32:35

21

尝试:

import Data.List.Split 
> splitEvery 2 [4,1,6,1,7,3,5,3] 
[[4,1],[6,1],[7,3],[5,3]] 
+7

您必须首先安装[split](http://hackage.haskell.org/package/split)软件包。 – ehird 2011-12-30 15:36:30

+3

对于像我这样的初学者来说 - 那意味着运行'cabal install split' – 2015-03-06 17:20:10

+4

其实,'splitEvery'还是推荐的吗? ':1:1:警告: 在使用“splitEvery” 推荐使用: “使用chunksOf”' – 2015-03-06 17:20:51

5

,我喜欢另一种解决方案是:

splitEvery :: Int -> [a] -> [[a]] 
splitEvery n = takeWhile (not.null) . map (take n) . iterate (drop n) 
2

又一解决方案:

split :: Int -> [a] -> [[a]] 
split n = unfoldr (\s -> if null s then Nothing else Just $ splitAt n s) 
0

我知道这是旧的,但因为这似乎是人谁是后对于Haskell来说相当新颖,我觉得也想发布我的解决方案。我尝试用序曲来解决这个问题,只有:

sublist :: Int -> [a] -> [[a]] 
sublist n ls 
    | n <= 0 || null ls = [] 
    | otherwise = take n ls:sublist n (drop n ls) 

测试

sublist 3 [1,2,3,4,5,6] -- λ> [[1,2,3], [4,5,6]] 
sublist 5 [1,2,3]  -- λ> [[1,2,3]] 
sublist (-1) [1,2,3] -- λ> [] 
sublist 20 []   -- λ> [] 
6

Data.List.Split模块具有这样的chunksOf功能:

Prelude> import Data.List.Split 

Prelude Data.List.Split> chunksOf 3 [1,2,3,4,5,6,7,8,9,10] 
[[1,2,3],[4,5,6],[7,8,9],[10]] 
Prelude Data.List.Split> chunksOf 3 [] 
[] 

它似乎被安装默认在我的机器上,但你可能需要用cabal来获得它。