【问题标题】:How do you compute all combinations of lists within a list in Haskell?你如何计算 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]]]

标签: haskell functional-programming


【解决方案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]

【讨论】:

    猜你喜欢
    • 2017-12-27
    • 2023-03-17
    • 2015-11-12
    • 2021-03-02
    • 2010-10-22
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    相关资源
    最近更新 更多