我想在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
是生成第一个列表的函数。
目前这不起作用,我做错了什么?
答案 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))