你如何计算 Haskell 列表中的所有列表组合?

Posted

技术标签:

【中文标题】你如何计算 Haskell 列表中的所有列表组合?【英文标题】:How do you compute all combinations of lists within a list in Haskell? 【发布时间】:2022-01-16 08:50:25 【问题描述】:

正如问题所述,我有一个多维列表,我想计算一个列表,其中包含这些列表的所有可能组合。 我只有一个用于一维列表的函数,如下所示:

combinations :: [a] -> [[a]]
combinations xs = [ [x,y] | x <- xs, y <- xs]

【问题讨论】:

您的解决方案允许重复:您可以为列表[1,2,3] 生成[2,2]。这是预期的行为,还是“错误”?如果没有重复,看起来你想生成所有可能的排列。 是的,需要这种行为。这同样适用于列表中的列表组合。 但是combinations [1,2,3] 的输出是什么? [1,1,1][1,1,2] 等等?我们什么时候停止“挑选”元素?例如,我不太清楚combinations [1,2,3] 的预期输出应该是什么。 组合 [1,2,3] 的输出为:[[1,1],[1,2],[1,3],[2,1],[2,2 ],[2,3],[3,1],[3,2],[3,3]]。但是我不能对多维列表使用相同的解决方案。多维列表所需的输出如下所示:combinationsM [[1,2],[3,4]] = [[[1,2],[3,4]],[[3,4], [1,2]]] 如果你使用列表,比如[[1], [2,3]],它将作为组合返回[[[1],[1]], [[1], [2,3]], [[2,3], [1]], [[2,3], [2,3]]] 【参考方案1】:

多维列表所需的输出如下所示:combinationsM [[1,2],[3,4]] = [[[1,2],[3,4]],[[3,4],[1,2]]]

您的combinations 函数处理元素列表的列表。它只是看到一个列表,而这些列表中的项目就是列表,但是函数并不关心这个。对于[[1,2], [3,4]],它将因此返回:

ghci> combinations [[1,2], [3,4]]
[[[1,2],[1,2]],[[1,2],[3,4]],[[3,4],[1,2]],[[3,4],[3,4]]]

因此,它有两次[1,2][1,2][3,4][3,4][1,2] 以及两次[3,4] 的组合。

因此,您的函数已经返回子列表的组合。它只适用于任何类型的列表。

如果您想删除两次选择相同子列表的组合,您可以定义一个助手来选择一个元素并返回剩余元素的列表:

pick :: [a] -> [(a, [a])]
pick [] = []
pick (x:xs) = (x, xs) : map … …

部分留作练习。该函数应该进行递归调用,并在所有列表前面加上xmap … … 部分。

这意味着pick [1,4,2,5] 返回[(1, [4,2,5]), (2, [1,4,5]), (4, [1,2,5]), (5, [1,4,2])]

然后我们可以在不选择相同元素两次的情况下获得组合:

combinations :: [a] -> [[a]]
combinations xs = [[x, y] | (x, ys) <- pick xs, y <- ys]

返回一个 2 元组的列表可能会更好,这会为返回类型添加更多上下文,因为我们知道组合包含的项数不可能与 2 不同:

combinations :: [a] -> [[a]]
combinations xs = [(x, y) | (x, ys) <- pick xs, y <- ys]

【讨论】:

以上是关于你如何计算 Haskell 列表中的所有列表组合?的主要内容,如果未能解决你的问题,请参考以下文章

Haskell 总结了通过树的所有路径

如何计算列表的所有组合

你如何在 Haskell 中使用模式匹配和元组列表?

Haskell 示例中的函数组合

从 Prolog 到 Haskell 的思考——生成真值组合列表

比较列表haskell中的所有元素[重复]