Haskell连续的列表子列表

时间:2018-03-07 12:07:41

标签: list haskell

嗨我有这个小函数找到了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)  

6 个答案:

答案 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]]]