首页 > 解决方案 > LISP - 编写函数 (REMOVE EL),从列表所有级别的另一个列表中删除给定的原子或列表

问题描述

我有以下任务:

构建函数(REMOVE EL),从另一个列表中删除给定的原子或列表,这应该适用于列表的每个级别

例子 :

L=(A B A (B A C X ) X B)
(REMOVE A L ) -> (B (B C X) X B)

我写了以下代码:

(defun removeel(el tree)
  (mapcan (lambda(subtree)
            (cond ((null subtree) (list nil))
                  ((consp subtree) (list (removeel el subtree)))
                  ((eql subtree el) nil)
                  (t (list subtree))))
          tree))

问题是当我删除原子时,它工作得很好

(removeel 'B' (A B A (B A C X ) X B))
 (A A (A C X) X) 

但它不起作用如果我想删除一个列表

(removeel '(B A C X) ' (A B A (B A C X ) X B))
  (A B A (B A C X) X B)

应该怎么做才能使其也删除列表?

标签: lispcommon-lisp

解决方案


最简单的方法是引入可选的相等测试功能,如remove标准程序。

它可能看起来像这样:

(defun rem-rec (item data &key (test #'eql))
  (mapcar (lambda (x) (if (listp x)
                          (rem-rec item x :test test)
                          x))
      (remove item data :test test)))

CL-USER> (rem-rec 1 `(1 2 (3 4 (1 2 3)) (1 (1 2 3) 3 4)))
;;=> (2 (3 4 (2 3)) ((2 3) 3 4))

对于列表相等,您可以使用equal(或equalp更具体的)

CL-USER> (rem-rec '(1 2 3) '(1 2 (3 4 (1 2 3)) (1 (1 2 3) 3 4)) :test #'equal)
;;=> (1 2 (3 4) (1 3 4))

推荐阅读