LISP - 从具有嵌套列表的列表中删除元素

时间:2012-04-30 09:36:01

标签: lisp common-lisp

我需要从包含内部列表的列表中删除一个元素。应从每个内部列表中删除预定义元素。

我已开始使用以下代码:

(SETQ L2 '(a b ( a 2 b) c 1 2 (D b (a s 4 2) c 1 2 a) a )) ; defined my list 

; Created a function for element removing
(defun elimina (x l &optional l0)
(cond (( null l)(reverse l0))
((eq x (car l))(elimina x (cdr l) l0))
(T (elimina x (cdr l) (cons (car l) l0))))
)

(ELIMINA 'a L2) 

但不幸的是,它只删除了嵌套列表之外的元素。

我试图创建一个额外的函数,它将从内部列表中删除元素。

(defun elimina-all (x l)
(cond ((LISTP (CAR L))(reverse l)(elimina x (car l)))
(T (elimina-all  x (CDR L)))
)
)

但仍未成功。

你能帮我解决一下吗?

提前谢谢。

3 个答案:

答案 0 :(得分:2)

首先,我建议你至少阅读这本书this page,它解释了(并且也提供了非常好的例子!)如何遍历树,但最重要的是,如何结合功能,从更简单的任务中利用更复杂的任务。

;; Note that this function is very similar to the built-in
;; `remove-if' function. Normally, you won't write this yourself
(defun remove-if-tree (tree predicate)
  (cond
    ((null tree) nil)
    ((funcall predicate (car tree))
     (remove-if-tree (cdr tree) predicate))
    ((listp (car tree))
     (cons (remove-if-tree (car tree) predicate)
           (remove-if-tree (cdr tree) predicate)))
    (t (cons (car tree)
             (remove-if-tree (cdr tree) predicate)))))

;; Note that the case of the symbol names doesn't matter
;; with the default settings of the reader table. I.e. `D' and `d'
;; are the same symbol, both uppercase.
;; Either use \ (backslash) or || (pipes
;; around the symbol name to preserve the case. Eg. \d is the
;; lowercase `d'. Similarly, |d| is a lowercase `d'.
(format t "result: ~s~&"
        (remove-if-tree
         '(a b (a 2 b) c 1 2 (D b (a s 4 2) c 1 2 a) a)
         #'(lambda (x) (or (equal 1 x) (equal x 'a)))))

以下是解决问题的一种方法的简短示例。阅读评论。

答案 1 :(得分:0)

也许是这样的:

(defun elimina (x l &optional l0)
  (cond ((null l) (reverse l0))
        ((eq x (car l)) (elimina x (cdr l) l0))
        (T (elimina x (cdr l) (cons (if (not (atom (car l))) 
                                        (elimina x (car l)) 
                                        (car l))
                                     l0)))))

答案 2 :(得分:0)

我一直在寻找与你相同的答案,不幸的是,我无法完全理解上面的答案,所以我只是在研究它,最后我在Lisp中得到了一个非常简单的功能,它完全符合你的要求。

(defun remove (a l)
(cond
    ((null l) ())
        ((listp (car l))(cons (remove a (car l))(remove a (cdr l))))
        ((eq (car l) a) (remove a (cdr l)))
        (t (cons (car l) (remove a (cdr l))))
        )
    )

该功能以两个简单的情况开始,它们是:' list is null'并且'第一个元素是一个列表'。在此之后,您将会神奇地"获取列表的car和没有给定元素的列表的cdr。要将其修复为整个列表的答案,您只需使用cons将它们组合在一起即可。