Haskell中的相交函数

时间:2018-09-12 21:21:18

标签: haskell

我在haskell中执行了此功能以进行相交,但是它不起作用。我知道辅助工作,但主要的没有。帮助请愿

myintersect ::  Eq a => [a] -> [a] -> [a]
myintersect a [] = a
myintersect l (h1:t1) = (myintersect (intersectaux h1 l) t1)

intersectaux :: Eq a => a -> [a] -> [a]
intersectaux _ [] = []
intersectaux a (h:t) = if a==h then h:intersectaux a t else intersectaux a t

1 个答案:

答案 0 :(得分:3)

当前方法存在的问题:

在您的方法中,intersectaux旨在过滤列表,以便仅保留等于a的元素。因此,这意味着对于intersectaux 4 [1,4,2,5],它将返回[4]。因此,这意味着在此“回合”之后,列表将只包含全部相同的元素:等于a的元素。

在下一个“回合”中,我们使用(可能)不同的元素进行过滤。如果我们使用等于前一个a的元素进行过滤,那么结果将等于给定的列表:一个仍只包含等于a的元素的列表。如果元素不同,则它将从列表中删除所有元素,因为a2 /= a1a1是“旧” a,而a2是“新” “ a),因此结果为空。

所有“回合”结束后,我们将基于上述结果返回仅包含相等元素或空列表的结果。

使用elem

的解决方案

两个列表的交集可以定义为:

  

包含所有在 first 列表和 second 列表中出现的所有元素的列表。

在Haskell中,列表的长度可以是无穷大,因此很难解决该问题。但是在这个答案中,我将忽略这一点:我们假设第二个列表的长度是有限的。更高级的策略(例如,每次在两个列表中每次使用有限数量的元素,然后计算这些有限集合的交集)。

为了计算交集,我们可以枚举第一个列表,对于该列表中的每个元素,请检查该元素是否也出现在第二个列表中。我们可以通过检查l来检查列表x是否包含元素elem x lelem :: Eq a => a -> [a] -> Bool

对于交点,我们有三种情况:

  1. 第一个列表已用尽(为空),在这种情况下,结果为空列表;
  2. 第一个列表不为空,并且该列表的第一个元素是第二个列表的元素,在这种情况下,我们 yield 该元素,然后递归到列表的尾部;和
  3. 第一个列表不为空,第二个列表中第一个元素没有 not 出现,然后递归到列表的尾部。

例如:

intersect :: Eq a => [a] -> [a] -> [a]
intersect [] _ = []
intersect (x:xs) l | elem x l = x : intersect xs l
                   | otherwise = intersect xs l

如果元素在第一个列表中出现多次次,则上面将多次产生元素(如果元素在第二个列表中多次出现,则一个“乘数”)。

如果元素可以Ord设置,或者元素为Hashable,则上述方法不是很有效。因此,仍可以(显着)改善上述情况。