0

我正在尝试编写一个 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]

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

4

5 回答 5

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]

或使用 drop and take

groupThree :: [a] -> [[a]]
groupThree [] = []
groupThree ls = (take 3 ls):groupThree (drop 3 ls)

它做同样的事情。

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

reGroup [xs,ls] y

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

蓄能器的正确使用是

reGroup back [] = back
reGroup back ls = reGroup (back ++ [take 3 ls]) (drop 3 ls)

不幸的是,这是非常低效的,因为您要附加到列表的末尾(花费的时间与该列表的长度成正比......模懒惰)。相反,您应该使用

reGroup back [] = reverse back
reGroup back ls = reGroup ((take 3 ls):back) (drop 3 ls)

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

于 2013-03-07T22:21:05.077 回答
4
 [[a]]

只是一个包含一个元素的列表,如 [[1]]。

因此,在一次递归之后,您可以从

reGroup [[]] [1,2,3,4,5,6,7,8,9]

reGroup [[1,2,3]] [4,5,6,7,8,9]

但是对于这种情况(一个包含 3 个元素的列表)没有定义模式。

于 2013-03-07T22:18:05.147 回答
2

尝试这个:

reGroup xs n =
    if drop n xs == []
    then [take n xs]
    else [take n xs] ++ (reGroup (drop n xs) n)

可能不是最有效的,但这是一个开始。

它输出:

> reGroup [1..9]
[[1,2,3],[4,5,6],[7,8,9]]
> reGroup [1..10]
[[1,2,3],[4,5,6],[7,8,9],[10]]

而您收到该错误的原因是因为您没有涵盖该函数可以匹配的所有模式。_尝试为您的基本案例投入一两个。

于 2013-03-07T22:18:02.470 回答
1

将您的代码稍微更改为此

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

做这项工作。

于 2013-03-07T22:23:58.213 回答
0
take3 :: [a] -> [[a]]
take3 [] = []
take3 (x:[]) = [[x]]
take3 (x:y:[]) = [[x,y]]
take3 (x:y:z:xs) = [[x,y,z]] ++ take3 xs
于 2013-03-07T22:26:47.093 回答