2013-03-07 72 views
0

我正在嘗試編寫一個Haskell代碼,它接受一個列表並返回列表。當我這樣做,如下面的代碼,我得到「的功能重組非詳盡模式」在Haskell中將相同長度的子列表打破列表

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]]。我做錯了什麼或有人能告訴我一個簡單的方法?

回答

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] 

或者用降,並採取

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) 

不幸的是,這是非常低效的,因爲要附加到列表的末尾(以時間比例到該列表的長度...模lazieness )。相反,你應該使用

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

雖然我不喜歡的累加器的版本更好,因爲它是懶惰(因此可以處理無窮的列表)。

+0

+1尼斯使用模式匹配 – 2013-03-07 22:23:11

+2

的(我認爲你有1太多的括號層在'[其他]'。) – huon 2013-03-07 22:28:19

+0

@dbaupp現在固定。 – 2013-03-07 23:13:42

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]] 

而且你得到這個錯誤的原因是因爲你還沒有覆蓋所有的功能可以匹配的模式。嘗試投擲一個_或兩個爲您的基本情況。

4
[[a]] 

只是用一種元素的列表列表,如[[1]]。

所以一個遞歸後,你從

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

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

但這種情況下(與3個元素的列表清單)是沒有定義的模式。

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); 

做這項工作。

0
take3 :: [a] -> [[a]] 
take3 [] = [] 
take3 (x:[]) = [[x]] 
take3 (x:y:[]) = [[x,y]] 
take3 (x:y:z:xs) = [[x,y,z]] ++ take3 xs 
相關問題