如何递归遍历2个列表

时间:2019-09-10 00:50:27

标签: recursion common-lisp

对于家庭作业问题,如果列表中的一部分位于另一个列表中,则必须删除列表中的重复项。预期结果应该是这样:

(remove-redundant '((R (1 2 3 8 e 4 7 6 5))
                    (U (e 2 3 1 8 4 7 6 5))
                    (D (1 2 3 7 8 4 e 6 5)))

                  '((D (1 2 3 e 8 4 7 6 5))
                    (L (e 2 3 1 8 4 7 6 5))
                    (U (2 e 3 1 8 4 7 6 5))
                    (U (2 8 3 1 e 4 7 6 5))))

返回:

((R (1 2 3 8 e 4 7 6 5)) (D (1 2 3 7 8 4 e 6 5)))

应该检查每个列表中的列表是否存在,因为第一个参数在第二个位置出现。如果确实出现,则将其从第一个列表中删除。基本上,如果(1 2 3 e 8 4 7 6 5)与第一个列表中的内容匹配,则将其从第一个列表中删除。我需要递归地执行此操作,它应该是一个功能程序。

我已经尝试过遍历该列表,但是不会重置(即它将检查第二个列表中第一个列表的开头,然后返回。

(defun same-state (l1 l2)
   (if (equal (cadr l1) (cadr l2)) t nil))

(defun remove-redundant (l1 l2)
  (cond
     ((null l2) l1)
     ((null l1) nil)
     ((same-state (car l1) (car l2)) (remove-redundant (cdr l1) (cdr l2))
     (T (remove-redundant l1 (cdr l2)))))

2 个答案:

答案 0 :(得分:1)

您已经接近,但是在t表格的cond情况下,您想要保留的单元格应该有一些堆积, 例如。

;; ...
(t
 (cons (car l1) (remove-redundant (cdr l1) (cdr l2))))

,并且当您检查l1中是否存在l2的第一个元素时,应该进行另一个循环或递归来检查l2中的所有元素,例如。

(defun same-state (l1 l2)
  (find l1 l2 :key #'cadr :test #'equal))

(defun remove-redundant (l1 l2)
  (cond
    ((null l2) l1)
    ((null l1) nil)
    ((same-state (cadar l1) l2)
     (remove-redundant (cdr l1) (cdr l2)))
    (t (cons (car l1)
             (remove-redundant (cdr l1) (cdr l2))))))
;; => ((R (1 2 3 8 e 4 7 6 5)) (D (1 2 3 7 8 4 e 6 5)))

答案 1 :(得分:0)

您将需要两个循环:一个循环通过第一个列表,然后每个循环一个以在第二个列表中找到匹配项。

相关问题