如何在特定条件下将列表拆分为多个组



我想把一个列表分成n个元素的组。例如:

n = 2
[1, 2, 3, 4, 5, 6] ->[[1, 2], [3, 4], [5,6]]
n = 3
[1, 2, 3, 4, 5, 6] -> [[1, 2, 3] [4, 5, 6]]

我尝试实现一个函数,如果n为0或大于列表长度,则返回n;如果n小于列表长度,返回拟合列表。

split :: Int -> [a] -> Either Int [[a]]
split n [a]
|n <= lenght [a] = Right n (take n [a]) : (split n (drop n [a]))
|n == 0 = Left n
|otherwise = Left n

然而,我得到了一个";变量不在范围内";错误我已经试过了,但是我被卡住了。我在数据类型上犯了错误吗?

您在lenghtlength之间有一个拼写错误,但如果我们更改它,仍然存在错误。

如果我们观察Right n (take n [a]),我们可以看到RightLeft只接受一个参数。

您的模式split n [a]也只匹配具有单个元素的列表。

让我们把它分解成更小的部分。创建一个拆分列表的函数非常简单。

split' n [] = []
split' n lst = take n lst : (split' n $ drop n lst)
Prelude> split' 3 [1,2,3,4,5,6]
[[1,2,3],[4,5,6]]

现在,将其设为split的本地,以合并您指定的检查并返回所需的Either类型,就很简单了。

split :: Int -> [a] -> Either Int [[a]]
split n [] = Left n
split n lst 
| n == 0 || n > length lst = Left n
| otherwise = Right lst'
where 
split' n [] = []
split' n lst = take n lst : (split' n $ drop n lst)
lst' = split' n lst

最新更新