【问题标题】:Haskell Cartesian Product Recursively [duplicate]Haskell笛卡尔积递归[重复]
【发布时间】:2013-02-15 03:50:04
【问题描述】:

我知道如何使用列表推导来做到这一点,但是如何实现一个函数,在给定两个集合的情况下递归计算笛卡尔积?

这就是我被困的地方(我是菜鸟)

crossProd :: [Int] -> [Int] -> [(Int,Int)]
crossProd xs ys | xs == [] || ys == [] = []
                | otherwise = (head xs, head ys) : crossProd (tail xs) (ys)

这个输出给了我

[(1,4),(1,5),(1,6)]

如果集合分别是[1,2,3][4,5,6].. 剩下的我该怎么办?

【问题讨论】:

  • 尝试写一个更简单的案例:crossProdAux :: Int -> [Int] -> [(Int,Int)]
  • 这很自然地写成列表理解

标签: haskell cartesian-product


【解决方案1】:

最基本的情况是这样的:

{-crossProdAux :: Int -> [Int] -> [(Int,Int)]-}
crossProdAux x []    = []
crossProdAux x (a:b) = (x, a):(crossProdAux x b)

{-crossProd :: [Int] -> [Int] -> [(Int,Int)]-}
crossProd [] ys   = []
crossProd (a:b) ys= (crossProdAux a ys)++(crossProd b ys)

【讨论】:

  • 我很好奇,你为什么要注释掉你的类型签名?
  • 可能是因为该函数适用于所有类型,而不仅仅是 Int。
  • 是的......我不想在我的答案中向代码中添加不精确的信息(或者,更重要的是混淆 OP)。
【解决方案2】:

这可以在一个函数中完成:

crossProd :: [a] -> [b] -> [(a, b)]
crossProd (x:xs) ys = map (\y -> (x, y)) ys ++ crossProd xs ys
crossProd _      _  = []

请注意,我已经概括了您的类型,因此这适用于任何 ab,而不仅仅是 Ints。

此功能的关键是了解您希望将第一个列表中的每个元素与第二个列表中的每个元素配对。因此,此解决方案从第一个列表中获取一个元素 x,并将其与 ys 中的每个元素配对。这是通过映射一个函数来完成的,该函数从ys 中获取每个值y,并将其转换为一对(x, y)。我们将其添加到列表的其余部分xs 的递归前面。

在基本情况下,没有任何东西可以配对,所以输出为空。

【讨论】:

    猜你喜欢
    • 2011-09-18
    • 2016-11-22
    • 2012-02-24
    • 2016-05-07
    • 2012-04-24
    • 1970-01-01
    • 2016-06-26
    • 2023-04-10
    • 2011-02-06
    相关资源
    最近更新 更多