你如何找到列表的所有子序列?

时间:2011-03-21 04:49:23

标签: haskell

我正在努力学习如何列出理解,我正试图找到一种方法来找到列表的所有子序列,但我不太确定如何去做。有谁可以帮助我?

4 个答案:

答案 0 :(得分:17)

另一个有趣的解决方案:

filterM (const [True,False]) [1,2,3]

我按如下方式阅读:返回包括或不包括列表元素的可能组合。这种解释可能没有使用正确的术语,但这是我直观地理解它的方式。 const为每个元素计算[True,False],因此每个元素都包含在结果中或不包含在结果中。使用filterM,此处的谓词位于列表monad中,因此我们会得到可能结果的列表。

答案 1 :(得分:16)

如果您想要访问此功能,可以使用subsequences中的Data.List功能。

subsequences [1,2,3]
>>> [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

如果您想知道它是如何实现的,您可以查看source code上提供的Hackage功能。

在这种情况下,它是:

subsequences            :: [a] -> [[a]]
subsequences xs         =  [] : nonEmptySubsequences xs

nonEmptySubsequences         :: [a] -> [[a]]
nonEmptySubsequences []      =  []
nonEmptySubsequences (x:xs)  =  [x] : foldr f [] (nonEmptySubsequences xs)
  where f ys r = ys : (x : ys) : r

答案 2 :(得分:10)

Ezra的答案涵盖了所有子序列,但如果你只想要连续的子序列,你可以使用:

import Data.List
continuousSubSeqs = filter (not . null) . concatMap inits . tails

你得到了

Prelude Data.List> continuousSubSeqs "asdf"
["a","as","asd","asdf","s","sd","sdf","d","df","f"]

以上内容也可以写成列表理解:

import Data.List
continuousSubSeqs ls = [t | i <- inits ls, t <- tails i, not $ null t]

答案 3 :(得分:0)

我非常喜欢@danlei对它的表达性的回答(如果你理解列表引入的非确定性)。但是你不需要Monads。有一个应用程序解决方案也具有该表达性,同时返回的结果与Data.List库中基于 foldr 的解决方案的顺序完全相同。

subs [] = [[]]
subs (x:xs) = subs xs <**> [id, (x :)]

对我来说,一旦你理解了列表如何提供非确定性(它们比它们作为一个简单的数据结构更强大和有用),这比 foldr 实现更容易理解

与库代码相比,它还有两个有趣的功能:

  1. 更改它可以很容易地将替换为任何幺半群函数(或使其具有通用性,以便它可以与任何幺半群一起使用)。
  2. 也很容易改变它以适用于任何可折叠的情况,其中也有一个monoid实例(尽管任何可折叠的 toList ,因此这是次要的)。
  3. (当然,Data.List实现,使用 foldr ,避免了外部依赖)

    例如......

    xorSubs [] = [0]
    xorSubs (x:xs) = xorSubs xs <**> [id, xor x]
    

    将有效计算列表的所有子序列的 xor 。如果列表包含以 1:2 开头的多个子序列(但只有一个 1 2 的实例), xor 1 2 < / strong>计算一次,并且该值与包含 1:2 的所有子序列共享。这比在子序列的输出中的每个列表上折叠 xor 更有效。

    由于 0 对于 xor 的monoid实例 mempty ,因此不应该很难看到如何重写它是

    msubs :: Monoid a => [a] -> [a]