嗨我有这个小函数找到了set的powerset但是我需要所有连续的子列表。 [1,2,3] -> [[],[1],[2],[3],[1,2],[2,3],[1,2,3]]
而非[[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]]
有没有办法修复此功能以实现我想要的效果?
sublists :: [a] -> [[a]]
sublists [] = [[]]
sublists (x:xs) = sublists xs ++ map (x:) (sublists xs)
答案 0 :(得分:6)
它不是很优雅,但您可以使用divvy
中的Data.List.Split
:
xs = [1,2,3]
[] : concat [ divvy n 1 xs | n <- [1..length xs] ]
-- [[],[1],[2],[3],[1,2],[2,3],[1,2,3]]
答案 1 :(得分:2)
迈克尔科尔的答案是不可建立的 Divvy已经返回[[a]]所以列表理解返回[[[a]]]。我只想添加评论,但没有足够的声誉来做到这一点。 使用concat。
sublists xs = [] : concat [ divvy n 1 xs | n <- [1..length xs]]
答案 2 :(得分:1)
我不确定您是否只想要已有的结果,但是要使用不同的元素排列。在这种情况下,一个简单而不是优雅的方式将在执行sublists
后进行排序。决定元素顺序的函数是:
subCompare x y = case (compare (length x) (length y)) of
EQ -> compare x y
s -> s
这意味着,按长度进行比较,但如果它们具有相同的长度,则按元素顺序进行比较。 然后:
> sortBy subCompare (sublists [1,2,3])
[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
答案 3 :(得分:1)
这几乎是一个简单的递归,因为如果我们想要sublists [1,2,3,4]
并且我们已经有了尾部的子列表,那就是......
[[], [2], [3], [4], [2,3], [3,4], [2,3,4]]
...很明显,要处理新元素1
,我们需要添加的新子列表包括[1]
,[1,2]
,[1,2,3]
和{{ 1}}。问题是这些新的地方并不明显
应插入子列表。
为了使它更容易,我们可以做一个稍微不同的递归,它保留了子列表 每个长度在他们自己的列表中分开,所以我们将
[1,2,3,4]
现在更明显的是插入新的位置 子列表。
最终结果只是串联。
[[[]],
[[2], [3], [4]],
[[2,3], [3,4]],
[[2,3,4]]]
注意:
我们需要将withX和withoutX设为相同的长度
zipWith没有提前用完,因为sublists :: [a] -> [[a]]
sublists = concat . sublists'
sublists' :: [a] -> [[[a]]]
sublists' [] = [[[]]]
sublists' (x:xs) = zipWith (++) withX withoutX
where
ysss = sublists' xs
withX = [] : [[x:ys] | ys:_ <- ysss]
withoutX = ysss ++ [[]]
已经包含了
我们需要不的零长度子列表包含在withX中。
我本可以使用withoutX
撰写withX
,但那样会
制作新的列表,而不是分享inits (x:xs)
中的一些列表。
(尽管最大分享是否有益有时取决于你的方式
消耗结果。)
ysss
也可以写为sublists'
。
答案 4 :(得分:1)
虽然不符合您要求的顺序,但
import Control.Monad((<=<))
import Data.List(inits, tails)
-- inits [x, y, z, ...] = [[], [x], [x, y], [x, y, z], ...]
-- tails [x, y, z, ...] = [[x, y, z, ...], [y, z, ...], [z, ...], [...], ..., []]
-- (f <=< g) x = do y <- g x
-- f y
-- (f . g) x = let y = g x
-- in f y
sublists = ([]:) . (tail . inits) <=< tails
这使用了列表monad模型非确定性的事实:tails
非确定性地选择子列表开始的位置,inits
选择它结束的位置,有一些重要的是为空列表获得更好的(?)行为,列表monad负责迭代开始和结束的所有可能组合。
答案 5 :(得分:1)
我不确定是否理解这个问题,但如果是这样,您可以使用combine
包的combinat
:
> import Math-Combinat-Sets
> map (`combine` [1,2,3]) [0..3]
[[[]],[[1],[2],[3]],[[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]],[[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],[1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]]