我正在寻找一个函数f
,给定一个n
元素列表,该函数计算一个n
个长度为n-1
的子列表。此外,第n个子列表应包含除原始列表的第n个元素以外的所有元素。例如:
f [1..4] == [[2,3,4], [1,3,4], [1,2,4], [1,2,3]]
我找到了一个似乎可行的解决方案,但看起来并不直观:
f :: [a] -> [[a]]
f [] = []
f xs = reverse $ go (length xs - 1) xs
where
go 0 _ = [[]]
go n xs = [ y:ys | y:xs' <- tails xs, ys <- go (n-1) xs' ]
有什么建议可以提供更合理,性能更合理的解决方案?
答案 0 :(得分:8)
f xs = [ ys ++ zs | (ys, _ : zs) <- zip (inits xs) (tails xs) ]
inits
和tails
依次为您提供所有前缀和后缀(请看一下zip (inits xs) (tails xs)
的结果)。列表推导从每个非空后缀(_ : zs
)中取出一个元素,然后将其余元素串联在一起。
答案 1 :(得分:1)
您可以通过观察作业问题包含一个递归结构来简化很多工作,该递归结构与沿列表本身的递归完全匹配。如果您对输入进行模式匹配且非空,则它具有列表的第一个元素,然后是列表的其余元素。列表的其余部分整齐地对应于没有第一个元素的原始列表,因此它应该是第一个输出。然后是递归-获得其余结果只是将f
直接应用到列表的其余部分,然后固定值,使它们的长度正确,并从正确的元素开始。