Lisp - 从另一个对列表中删除对列表的实例

时间:2012-01-04 21:37:02

标签: lisp common-lisp

我想在lisp中编写一个函数,该函数接受两个对列表,并从第二个列表中删除所有第一个列表。 例如,如果我们有list1 ((a b)(cd))list2 ((g h)(a b)(j i)),则通过调用此函数,结果将为((g h)(j i))

到目前为止,我有以下代码(不起作用):

(defun retira(obj l1)
  (cond ((null l1) ())
        ((equal obj (first l1)) (retira obj (rest l1)))
        (t (cons (first l1) (retira obj (rest l1))))))

(defun retira-ocupadas (tabuleiro lista-adj)
  (if (equal (first (todos-ocupados tabuleiro)) (first lista-adj))
    (retira (car (todos-ocupados tabuleiro)) lista-adj))

  (retira-ocupadas (rest (todos-ocupados tabuleiro)) (rest lista-adj))) 

其中retira应该删除列表中所有出现的对象,retira-ocupadas应该注意比较,如果第一个列表中的对象等于第二个列表中的对象。 Todos-ocupados是生成第一个列表的函数。

目前这不起作用,我做错了什么?

4 个答案:

答案 0 :(得分:3)

您想删除第二个列表中属于第一个列表的任何元素。

(defun remove-list (list-to-remove target-list)
  (remove-if (lambda (element)
               (member element list-to-remove
                       :test #'equal))
             target-list))

请注意equal的定义,也许您想要equalp(或者您可能需要自己编写pair-equal)。

答案 1 :(得分:2)

(defun list-difference (list1 list2 &key (test #'eql))
  (loop for item in list1
        unless (member item list2 :test test)
        collect item))

示例:

CL-USER > (list-difference '((g h) (a b) (j i))
                           '((a b) (cd))
                           :test #'equal)
((G H) (J I))

答案 2 :(得分:1)

这是你想要做的吗?

(defun multi-remove (a b)
  (loop for e in b
        do (setf a (remove e a)))

这会遍历b的每个元素,并在。

中破坏性地删除它的所有出现

答案 3 :(得分:0)

set-difference会执行此操作,但不一定会保留列表的顺序:

? (let ((list1 '((a b) (c d)))
        (list2 '((g h) (a b) (j i))))
    (set-difference list2 list1 :test 'equal))
((J I) (G H))