我有Int
的列表列表,我需要在列表列表的最后一个列表中添加Int
值。我怎样才能做到这一点?我的尝试低于
f :: [[Int]] -> [Int] -> Int -> Int -> Int -> [[Int]]
f xs [] cur done total = [[]]
f xs xs2 cur done total = do
if total >= length xs2 then
xs
else
if done == fib cur then
f (xs ++ [[]]) xs2 (cur + 1) 0 total
else
f ((last xs) ++ [[xs2!!total]]) xs2 cur (done + 1) (total + 1)
问题是:
我们有一个Int A
列表
我们需要在N
列表B_1 ,..., B_n
上对其进行调整,B_i
的长度为第i个斐波纳契数。
如果我们的代码中有[1 , 2 , 3 , 4 , 5 , 6 , 7]
(xs2
)列表
结果应为[[1] , [2] , [3 , 4] , [5 , 6 , 7]]
答案 0 :(得分:3)
处理这类问题的简单方法是将问题分解为子问题。在这种情况下,您想要更改列表中的最后一项。您想要更改它的方式是向其添加项目。
首先让我们解决更改列表的最后一项的问题。我们将通过将函数应用于最后一项而不是任何其他项来完成此操作。
onLast :: [a] -> (a -> a) -> [a]
onLast xs f = go xs
where
go [] = []
go [x] = [f x]
go (x:xs) = x:go xs
您想通过添加额外的值来更改列表中的最后一项,您可以使用(++ [value])
来执行此操作。
将两者与您要添加的值(xs2!!total
)相结合,我们得到
(onLast xs (++ [xs2!!total]))
答案 1 :(得分:0)
你的方法使用do
块,这有点奇怪,因为do
块通常用于 monads 。此外,还不清楚cur
,done
和total
正在做什么。此外,您使用(!!) :: [a] -> Int -> a
和length :: [a] -> Int
。这些函数的问题是它们在 O(n)中运行,因此它也使代码效率低下。
根据更改的规范,您希望拆分列表中的列表,其长度为 Fibonacci数字。在这种情况下,签名应为:
f :: [a] -> [[a]]
因为输入时会给出一个数字列表,作为输出,您将返回一个数字列表。然后我们可以将其实现为:
f :: [a] -> [[a]]
f = g 0 1
where g _ _ [] = []
g a b xs = xa : g b (a+b) xb
where (xa,xb) = splitAt b xs
这会产生:
*Main> f [1,2,3,4,5,6]
[[1],[2],[3,4],[5,6]]
*Main> f [1,2,3,4,5,6,7]
[[1],[2],[3,4],[5,6,7]]
*Main> f [1,2,3,4,5,6,7,8]
[[1],[2],[3,4],[5,6,7],[8]]
*Main> f [1,2,3,4,5,6,7,8,9]
[[1],[2],[3,4],[5,6,7],[8,9]]
代码的工作方式如下:我们声明f = g 0 1
,因此我们将f
的参数传递给g
,但g
也获得了0
和a 1
(第一个斐波纳契数)。
每次迭代g
检查我们是否到达列表的末尾。如果是这样,我们也返回一个空列表。否则,我们确定最后一个Fibonacci数(b
),并使用splitAt
获取我们处理的列表的第一个b
元素,以及余数。然后我们将第一部分作为列表的头部发出,对于尾部,我们计算下一个斐波纳契数,并将其传递给g
,尾部为splitAt
。
答案 2 :(得分:0)
f :: [[Int]] -> Int -> [[Int]]
f [] _ = []
f xs i = (take n xs) ++ [[x + i | x <- last xs]]
where n = (length xs) - 1
last = head . (drop n)
例如,
*Main> f [[1, 2, 3], [], [4, 5, 6]] 5
[[1,2,3],[],[9,10,11]]
*Main> f [[1, 2, 3]] 5
[[6,7,8]]
*Main> f [] 3