我确信这是一个相当普遍的事情,但我找不到任何东西(我的网络搜索功能不强)。
我有一个函数可以将列表分组为每个N个元素的列表列表,如果列表的长度不能被N整除,则最终子列表小于N.一些例子:
groupEvery 2 [1,2,3,4] = [[1,2],[3,4]]
groupEvery 4 [1,2,3,4,5,6,7,8,9,10] = [[1,2,3,4], [5,6,7,8], [9,10]]
我想要的是获取一个列表和一个正整数 n (在上面的例子中 n 可以说是2和3)并将其划分为 n 列表的新列表。它应该在任何类型的列表上工作,并生成尺寸尽可能小的子列表。
所以我想:
fairPartition 3 [1,2,3,4,5,6,7,8,9,10] = [[1,2,3,4], [5,6,7], [8,9,10]]
或任何子列表组合,只要有长度为3和长度为4的两个。
使用groupEvery的天真尝试:
fairPartition :: Int -> [a] -> [[a]]
fairPartition n xs = groupEvery ((length xs `div` n) + 1) xs
fairPartition 4 [1..10] = [[1,2,3],[4,5,6],[7,8,9],[10]]
但是你可以看到(3,3,3,1)不是公平的长度分布,对于较小长度的列表,它甚至没有返回正确数量的子列表:
# Haskell, at GHCi
*Main> let size = 4 in map (\l -> length . fairPartition 4 $ [1..l]) [size..25]
[2,3,3,4,3,3,4,4,3,4,4,4,4,4,4,4,4,4,4,4,4,4]
我想要一个{pseudo,actual} -code函数或解释,可以很容易地翻译成Haskell(身份翻译将是最好的!)。
感谢。
答案 0 :(得分:3)
您可以使用split
包的splitPlaces
功能。
import Data.List.Split
fairPartition n xs = case length xs `quotRem` n of
(q, r) -> splitPlaces (replicate r (q+1) ++ replicate (n-r) q) xs