从嵌套列表中删除

时间:2014-08-11 00:14:24

标签: lisp common-lisp

我有一项困扰我的家庭作业!我必须创建一个函数goo(A L),它将删除L中的每个A,它也必须在嵌套列表上工作。

这是我到目前为止所得到的

(defun goo(A L)
(cond ((null L) nil) ; if list is null, return nil
(T  ; else list is not null
    (cond ((atom (car L))) ;if car L is an atom
        ((cond ((equal A (car L)) (goo A (cdr L)))  ;if car L = A, call goo A cdr L
            (T (cons (car L) (goo A (cdr L)))))) ;if car L != A, 
    (T (cons (goo A (car L)) (goo A (cdr L))))))    ;else car L is not atom, call goo on car L and call goo on cdr L
))

无论我给它什么,这个函数都会返回True。

3 个答案:

答案 0 :(得分:2)

你parens搞砸了。移动(atom (car L))周围的最后一个paren以包含下一个cond表达式。我建议使用一个显示匹配的parens的IDE。

至于样式,如果你不知道,cond can accept multiple clauses。这样您就不需要再次使用t,然后再使用cond。如果您只测试单个谓词并根据该谓词做出决定,您也可以use 'if'

答案 1 :(得分:0)

  

注意:这最初是作为revision 2中原始提问者对问题的修改而发布的。

我尝试了另一种方法,现在正在工作。

(defun goo(A L)
(cond ((null L) nil)
      ((atom (car L)) (cond ((equal A (car L)) (goo A (cdr L)))
                        (T (cons (car L) (goo A (cdr L))))))
      (T (cons (goo A (car L)) (goo A (cdr L))))
))
  

注意2:通常应按照这样的格式显示程序结构:

(defun goo (a l)
  (cond ((null l) nil)
        ((atom (car l))
         (cond ((equal a (car l))
                (goo a (cdr l)))
               (t (cons (car l)
                        (goo a (cdr l))))))
        (t (cons (goo a (car l))
                 (goo a (cdr l))))))

答案 2 :(得分:0)

我认为将此替换为 trees 问题可能更容易。很容易定义一个函数,它接受一个树并替换满足测试的子树。有一个标准函数subst-if可以做到这一点,但它用相同的东西替换每个匹配的子树。如果我们用从子树计算的值替换元素,对我们来说会更有用:

(defun %subst-if (new test tree)
  "Replace subtrees of TREE that satisfy TEST with the result 
of calling NEW with the subtree."
  (cond
    ;; If tree satifies the test, return (new tree).
    ((funcall test tree)
     (funcall new tree))
    ;; If tree is a cons, recurse.
    ((consp tree)
     (cons (%subst-if new test (car tree))
           (%subst-if new test (cdr tree))))
    ;; Otherwise, just return the leaf.
    (tree)))

有了这个,它很容易定义我们需要的功能。当一个元素X出现在嵌套列表结构的某个地方时,它意味着有一个cons小区,其汽车是X.我们想用它的cdr替换那个cons小区,但是也要在单元的cdr上进行递归。这并不难:

(defun replace* (x list &key (test 'eql))
  "Remove occurrences of X in LIST and  its sublists."
  (%subst-if
   (lambda (cons)
     "Replace elements of the form (X . more) with
      (replace* x more :test test)."
     (replace* x (cdr cons) :test test))
   (lambda (subtree)
     "Detect subtrees of the form (X . more)."
     (and (consp subtree)
          (funcall test x (car subtree))))
   list))

(replace* 'a '(1 a (2 a 3) a 4 a 5))
;=> (1 (2 3) 4 5)