2011-12-03 48 views
0

我遇到了此lisp函数的问题。我想创建一个接收两个列表的函数,并验证第一个列表中的元素(全部)是否出现在第二个列表中,如果发生这种情况,它将返回True。Lisp - Lisp的元素出现在其他列表中

目前,我有以下代码:

(defun ocorre-listas (l1 l2) 
(dolist (elem1 l1) 
    (dolist (elem2 l2) 
     (if (equal elem1 elem2) 
      t)))) 

它不工作,符合市场预期。我应该试着做一个简单的递归吗?我真的没有得到如何我可以遍历这两个列表寻找相同的元素。

,我决定尝试没有dolists。这就是我现在所拥有的,它仍然不起作用。

(defun ocorre-listas (l1 l2) 
(cond ((null l1) nil) 
     ((null l2) nil) 
     ((if (/= (first l1)(first l2)) (ocorre-listas l1 (rest l2)))) 
     (t (if (= (first l1) (first l2)) (ocorre-listas (rest l1)(rest l2)))))) 

我收到一个警告,说“t”是一个未定义的函数。另外,我尝试的每个例子都返回null。我究竟做错了什么 ?

+1

正确缩进你的代码。看到表单被正确嵌套。 –

回答

1

在第二代码段,如果第一列表是空的,则其所有的元素都在第二个。

你不需要ifs因为你是内cond

测试之后,如果列表是空的,你只需要测试,如果第一个列表的第一个元素是在第二个和再次使用没有此元素的第一个列表调用函数

1

为了能够在同一时间在两个列表中的工作,关键是可能开始递归之前的列表进行排序。那么它应该是比较的第一个元素,并递归地应用相同的功能列表的其余部分,与一些汽车的一个简单的事情/ CDR魔法加当然...

+0

列表已经排序......最难的部分是获得CAR/CDR的魔法发生;) –

1

,而不是试图在一个做的一切功能,请考虑将其分成两个(或更多)功能,例如

  • 一个采用一个数和第二列表,并测试的数量是否出现在列表中
  • 另一种迭代的数量在第一列表中,并为每一个测试(使用第一功能)是否出现在第二个列表中。

除了DOLIST,可以考虑使用MAPCARFIND-IF(假设它们被允许在此分配。)​​

2

因此,您需要检查l1的every元素是否为l2的member。这些都是Common Lisp标准库中的函数,所以如果您允许使用它们,您可以使用它们构建一个简单的解决方案。

1

见Common Lisp的subsetp 谓词及其实施:

CL-USER> (subsetp '(1 2 3) '(1 2 3 4) 
T 
0

虽然有很多方法可以做到这一点,我会建议使用一个哈希表,以避免O(n^2)复杂。使用散列表,你可以达到O(n)的复杂性。

这里是联合功能

(defun my-union (a b) 
    (let ((h (make-hash-table :test #'equal))) 
    (mapcar (lambda (x) (setf (gethash x h) x)) a) 
    (mapcan (lambda (x) (when (gethash x h) (list x))) b))) 

这里是boths列表

(defun same-elements (a b) 
    (apply #'= (mapcar #'length (list (my-union a b) a b)))) 

这里的相同元素的功能测试是确保ab一个子集(你问什么功能)

(defun subset (a b) 
    (same-elements (my-union a b) a)) 
+0

注意:我的函数假定列表不包含重复项 – protist