【问题标题】:Generate all combinations of a 6 element list and apply a function to each combination生成 6 元素列表的所有组合并将函数应用于每个组合
【发布时间】:2016-05-13 01:45:19
【问题描述】:

我想生成一个 6 元素列表 [x1,x2,x3,x4,x5,x6] 的所有可能组合,其中每个 xi 是 0 到 20 之间的数字。

我想生成此类列表的所有可能组合,对每个列表应用一个函数(将列表作为输入并输出一个神奇的 Int),然后将结果输出到一个元组列表。所以元组列表看起来像

[([x11,x21,x31,x41,x51,x61],Int1), ([x12,x22,x32,x42,x52,x62],Int2), ...]

我手动尝试了这一点,但很快意识到组合太多,几乎不可能手动完成。

组合如 [0,0,0,0,0,0], [1,7,0,10,11,6], [7,7,7,7,6,6], [ 20,20,20,20,20,20] 等等。

我知道如何生成列表的所有组合并将它们放入列表列表中(因为我之前问过这个)

foo [] = [[]]
foo (x:xs) = foo xs ++ map (x:) (foo xs)

这次我想要实现的是不同的,因为我不是要在特定列表中生成不同的组合,而是要生成所有 6 个元素列表。

【问题讨论】:

  • 只有64000000(20^6)个,怎么“太多”了?您可能应该对实际问题使用更聪明的方法。这些神奇的整数是什么,你用它们做什么,你为什么需要这么多?
  • 我想你会在 List Comprehensions 上的 Haskell wiki 页面上找到这些示例很有帮助。
  • @Bergi 如果你真的阅读了周围的上下文,手工处理太多了。
  • @immibis,这可能是讽刺。 20⁶ 相当多,在许多情况下,您实际上并不需要它。不过,如果不知道实际问题,就不可能说出来。

标签: list haskell combinations


【解决方案1】:

据我所知,您需要 6 个列表 [0..20] 的笛卡尔积(此处用 × 表示)。

所以本质上是这样的:

[0..20]×[0..20]×[0..20]×[0..20]×[0..20]×[0..20]

这是 很多 个元素(准确地说是 85,766,121 个)。但是,这是可以做到的。

也许一个更容易理解的版本如下。

让我们定义一个函数cart,它可以对一个列表和一个列表的列表进行笛卡尔积:

let cart xs ls = [x:l | x <- xs, l <- ls]

此函数将从xs 中获取所有元素,并从ls 中获取所有元素,并构建一个包含所有可能连接的列表列表。

现在,我们需要一个基本案例。假设您想要一个 single 元素而不是六个元素的列表列表。您将如何应用我们的cart 功能?好吧,因为它将第一个参数中的每个元素添加到第二个参数中的每个元素,我们可以将单个空列表的列表作为第二个参数传递,并将[0..20] 作为第一个参数:

cart [0..20] [[]]

我们得到

[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20]]

太好了。现在我们只需将它应用到它自己的结果上 6 次,从 [[]] 开始:

foldr ($) [[]] $ replicate 6 (cart [0..20])

($) 是函数应用程序。

replicateM from Control.Monad(定义为sequence of n monadic actions:replicateM n x = sequence (replicate n x))在应用于列表时基本上是相同的(参见例如Why does application of `sequence` on List of Lists lead to computation of its Cartesian Product?,了解为什么会这样)所以简短的答案会是这样的:

replicateM 6 [0..20]

您可以在此之后映射它们,例如

map (\x -> (x, magicFunction x)) $ replicateM 6 [0..20]

【讨论】:

    【解决方案2】:

    foo f xs = map (\ys -&gt; (ys,f ys)) (replicateM (length xs) xs)

    这里replicateM (length xs) xs 将生成xs 中元素的所有组合。然后你只需映射它。

    GHCI 中的结果:

    >import Control.Monad
    >let foo f xs = map (\ys -> (ys,f ys)) (replicateM (length xs) xs)
    >foo sum [1,2]
    [([1,1],2),([1,2],3),([2,1],3),([2,2],4)]
    

    【讨论】:

      猜你喜欢
      • 2021-12-27
      • 2016-05-02
      • 2023-01-24
      • 2015-10-15
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      相关资源
      最近更新 更多