如果我有一个列表[a,b,c,d,e]
,如何在维持秩序的同时找到将元素加入子列表的各种方法。
输出应该看起来像这样
[ [[a], [b], [c], [d]]
, [[a,b], [c], [d]]
, [[a], [b,c], [d]]
, [[a], [b], [c,d]]
, [[a,b,c], [d]]
, [[a,b], [c,d]]
, [[a,b,c,d]]
]
答案 0 :(得分:2)
你可以这样做:
sublists :: [a] -> [[[a]]]
sublists [x] = [[[x]]]
sublists (x:xs) = sublists xs >>= \(y:ys) -> [[x]:y:ys, (x:y):ys]
这里的主要见解是没有逻辑方法将此扩展到空列表输入 - 唯一可行的候选者将是sublists [] = [[[]]]
但这会引入空列表(在这种情况下您不需要) 。
但是,这会激发一个有用的不变量:内部 - 内部(最里面)列表永远不会是空的(我们确保通过不在[[x]:y:ys, (x:y):ys]
中引入空列表来保持这种情况 - 我们唯一一次添加新列表列表[x]
,他们已经有一个元素)。这可以确保lambda中的模式匹配永远不会失败。
顺便说一句,如果它更清楚,可以使用do notation轻轻地重写:
sublists :: [a] -> [[[a]]]
sublists' [x] = [[[x]]]
sublists' (x:xs) = do
(y:ys) <- sublists' xs
[[x]:y:ys, (x:y):ys]
或concatMap
代替(>>=)
:
sublists'' :: [a] -> [[[a]]]
sublists'' [x] = [[[x]]]
sublists'' (x:xs) = concatMap (\(y:ys) -> [[x]:y:ys, (x:y):ys]) (sublists'' xs)