从Common Lisp中的列表中删除元素?

时间:2018-10-23 03:11:35

标签: recursion lisp common-lisp

我目前正在尝试(递归地)从所有级别的列表中删除找到的所有NIL。我已经知道如何从列表的顶层删除NIL,并且我认为在处理多个级别时,很多想法都是相同的,但是,我遇到了麻烦。

我从顶层删除Nil的代码:

(defun removeNILTop (L)
    (cond ( (NULL L) NIL) ;;list is empty
          ( (NULL (CAR L)) (removeNILTop( CDR L))) ;;Nil so skip it
          ( T (CONS( CAR L) (removeNILTop( CDR L)))) ;;not NIL so include it
    )
)

这是我从各个级别删除Nil的代码:

  (defun removeAll (l)
        (cond
            ((null l) NIL) ;;empty list
            ((null (car l)) (removeAll(cdr l))) ;;Nil so skip it
            ((atom (car l)) (cons (car l) (removeAll(cdr l)))) ;;not nil and is a atom so continue normally
            (T (cons( removeAll(car l) (removeAll(cdr l))))) ;;car is a list recurse into it
        )

    )

我考虑这个问题的方式是在第一个示例中,我忽略了列表中的什么车,只要它不为空,就保留它。但是,现在我很在乎,我应该检查汽车是否为

  • 一个原子而不是nil,如果是,那么我可以正常进行
  • 否则,如果它是一个列表,则应递归到其中,并将结果限制为cdr的结果。

但是,这显然不起作用,有任何提示吗?

2 个答案:

答案 0 :(得分:3)

您现在有关于car的三种情况。从当前单元格的角度来看它:

  • 当前单元格的carnil
  • 当前单元格的car是一个原子(而不是null)
  • 当前单元格的car是一个列表

关于cdr,假设嵌套了正确的列表,它将始终是con单元格或nil

如果您认为carcdr都需要递归,则需要递归。

关于命名:Lisp阅读器的标准行为是大写,因此显示的名称实际上是REMOVENILTOPREMOVEALL。约定是用小写字母名写成的小写字母名称,用短划线隔开:remove-nil-topremove-all。顺便说一下,我更喜欢remove-niltree-remove-nil这两个名字。

答案 1 :(得分:2)

(defun removeAll (l)
  (cond ((null l) NIL)
        ((null (car l)) (removeAll(cdr l))) 
        ((atom (car l)) (cons (car l) (removeAll (cdr l)))) 
        (T (cons (removeAll (car l)) (removeAll (cdr l))))))

您忘了在最后一个子句中用括号将removeAll上的第一个(car l)关闭。

您可以通过使用支持括号自动填充的编辑器来避免此类错误。并自动缩进代码。您使用什么编辑器?