我正在努力学习如何列出理解,我正试图找到一种方法来找到列表的所有子序列,但我不太确定如何去做。有谁可以帮助我?
答案 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 实现更容易理解
与库代码相比,它还有两个有趣的功能:
(当然,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]