将列表分成Haskell中相同长度的子列表

Ken*_*Ken 0 haskell

我正在尝试编写一个Haskell代码,它接受一个列表并返回一个列表列表.当我这样做,如下面的代码,我得到"函数reGroup中的非穷举模式"

reGroup :: [[Int]] -> [Int] -> [[Int]]
reGroup [[]] [] = [[]]
reGroup [[]] xs = reGroup [(take 3 xs)] (drop 3 xs)
reGroup [[a]] [] = [[a]]
reGroup [[a]] xs = reGroup [[a], (take 3 xs)] (drop 3 xs)

-- calling the reGroup function from another function as follow
reGroup [[]] [1,2,3,4,5,6,7,8,9]
Run Code Online (Sandbox Code Playgroud)

我想要的是[1,2,3,4,5,6,7,8,9]- > [[1,2,3], [4,5,6], [7,8,9]].我做错了什么或有人能告诉我一个简单的方法吗?

Phi*_* JF 7

没有累加器(第一个参数),尝试这样做可能更容易.然后我们会

groupThree :: [a] -> [[a]] --why only work with Ints?
--if the list begins with three elements, stick them in a group
--then group the remainder of the list
groupThree (a:b:c:more) = [a,b,c]:groupThree more
--grouping an empty list gives you an empty list
groupThree [] = []
--if we have some number of elements less than three
--we can just stick them in a list
groupThree other = [other]
Run Code Online (Sandbox Code Playgroud)

或使用drop and take

groupThree :: [a] -> [[a]]
groupThree [] = []
groupThree ls = (take 3 ls):groupThree (drop 3 ls)
Run Code Online (Sandbox Code Playgroud)

这完全是一回事.

你的代码不起作用的原因是

reGroup [xs,ls] y
Run Code Online (Sandbox Code Playgroud)

与您的任何情况都不匹配 - 您只有代码来处理第一个参数是一个元素的列表,该元素是空列表或只有一个元素的列表.

正确使用累加器将是

reGroup back [] = back
reGroup back ls = reGroup (back ++ [take 3 ls]) (drop 3 ls)
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是非常低效的,因为你追加到列表的末尾(花时间与该列表的长度成比例...模数懒惰).相反,你应该使用

reGroup back [] = reverse back
reGroup back ls = reGroup ((take 3 ls):back) (drop 3 ls)
Run Code Online (Sandbox Code Playgroud)

虽然我喜欢没有累加器的版本更好,因为它更懒惰(因此可以处理无限列表).

  • (我认为你在[[[other]]`中有太多的括号层.) (2认同)