【问题标题】:Haskell about recursion in list functionHaskell关于列表函数中的递归
【发布时间】:2017-06-22 15:42:48
【问题描述】:

我正在尝试创建一个需要两个列表并返回一个列表的函数(我是 haskell 的新手)。列表应该包含第一个列表中不在第二个列表中的所有元素,以及第二个列表中所有不在第一个列表中的元素。

所以:func [3,2,1,4] [2,5,1] 应该返回 [3,4,5]

我认为我的代码朝着正确的方向发展,但其中的某个地方是一个大错误。

func :: [Int] -> [Int] -> [Int]
func [] a = a
func a [] = a
func (x:xs) (y:ys) | elem x (y:ys) = filter (/=x) (y:ys)
                   | otherwise = func ys xs

【问题讨论】:

  • 你能解释一下最后两行吗,因为它们对我来说似乎没有多大意义......
  • 我认为您的意思是我的代码的最后 2 个。因此,如果 x 是列表的一个元素 (y:ys),则创建没有 x 的列表。而且我已经尝试使用递归来对 xs 做同样的事情,但现在它应该检查 ys 的第一个元素并查看 xs 中是否有其中一个元素。
  • 但是您没有执行递归调用,使用过滤后的列表。

标签: list function haskell recursion


【解决方案1】:

假装对这个问题领域没有任何经验或非常熟悉base 中的功能,我将重新表述您的问题陈述以描述我们想要的操作并向您展示我将如何处理它:

fun 在两个列表中的结果是:第一个的所有元素 列表,谁不在第二个和第二个列表中,谁不在 在第一个。

要开始在代码中表达这一点,请将“is”替换为=

func l1 l2 = (elementsOfFirstNotInSecond l1 l2) ++(elementsOfFirstNotInSecond l2 l1)

现在我们需要实现elementsOfFirstNotInSecond,所以让我们从单词开始:

elementsOfFirstNotInSecond 在两个列表中是:如果l1 是空的 list 则为空列表,否则为l1 的头部(我们称它为 "x") 是 l2 的成员,然后是 x 的成员 elementsOfFirstNotInSecondl1l2尾部。否则 (如果x 不是l2 中的不是)它只是 elementsOfFirstNotInSecond l1l2 的尾部

看看您是否可以使用尚未实现的函数(例如,您可能想要使用 (isAMemberOf :: Int -> [Int] -> Bool) 将其转换为 haskell,然后重复练习。

【讨论】:

    【解决方案2】:

    输出顺序重要吗?

    如果没有,您可以使用列表差异 (\\)Data.List

    Prelude > import Data.List
    Prelude Data.List> as = [3,2,1,4]
    Prelude Data.List> bs = [2,5,1]
    Prelude Data.List> notinSec = as \\ bs
    Prelude Data.List> notinFst = bs \\ as
    Prelude Data.List> ans = notinSec ++ notinFst 
    Prelude Data.List> ans
    [3,4,5]
    

    【讨论】:

      【解决方案3】:

      因为你想要递归并且是新的haskell,所以解决方案(朝着你的方向移动)就像

      func (x:xs) (y:ys) | elem x (y:ys) && (not (elem y (x:xs))) = func xs (filter (/=x) (y:ys))
                         | (not (elem x (y:ys))) && (elem y (x:xs)) = func (filter (/=y) (x:xs)) ys
                         | (elem x (y:ys)) && (elem y (x:xs)) = func (filter (/=y) (xs)) (filter (/=x) (ys))
                         | otherwise = x : y : (func xs ys)
      

      但您可以在学习路径的后期阶段看到这是多么的丑陋和愚蠢。 我建议您使用更简单、更简洁的替代方案。

      【讨论】:

      • 以及如何更简单或更好的方法来解决它?我只是认为如果我想解决这类问题,我需要使用递归。
      • 好吧,首先你可以使用非常简单的函数 func x y = (x union y) \\ (x intersect y) 。记得导入Data.List
      • 由于 SO 的代码格式,反引号不存在。因此,您可以使用此版本 func x y = (union x y) \\ (intersect x y) 或其在上述注释中的内联等效项与反引号。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 2011-07-16
      • 1970-01-01
      • 2016-08-03
      • 2016-05-06
      • 2023-04-09
      相关资源
      最近更新 更多