LISP函数删除nils

时间:2010-10-19 10:17:14

标签: function lisp

我想在LISP中编写一个函数,它将完全删除列表中的所有NILS。该列表可以嵌套,这意味着它可以包含其他列表。例如,列表'((状态L L L L)NIL(状态L L R L)NIL)应转换为'((状态L L L L)(状态L L R L))。

4 个答案:

答案 0 :(得分:10)

(defun remove-nil-recursively (x)
  (if (listp x)
    (mapcar #'remove-nil-recursively
            (remove nil x))
    x))

适用于您的示例:

[1]> (remove-nil-recursively '((state L L L L) NIL (state L L R L) NIL))
((STATE L L L L) (STATE L L R L))

使用嵌套列表:

[2]> (remove-nil-recursively '(NIL (state L L nil R L) NIL))
((STATE L L R L))

但请注意:

[3]> (remove-nil-recursively '(NIL (state L L (nil) R L) NIL))
((STATE L L NIL R L))

答案 1 :(得分:3)

保罗格雷厄姆称这个功能(重复出现在子列表中删除 - 如果)“修剪”在On Lisp中,p。它是实用功能之一。

(defun prune (test tree)
  (labels ((rec (tree acc)
              (cond
               ((null tree) (nreverse acc))
               ((consp (car tree))
                (rec (cdr tree)
                     (cons (rec (car tree) nil) acc)))
               (t (rec (cdr tree)
                       (if (funcall test (car tree))
                           acc
                         (cons (car tree) acc)))))))
    (rec tree nil)))

(prune #'evenp '(1 2 (3 (4 5) 6) 7 8 (9)))
(1 (3 (5)) 7 (9))

答案 2 :(得分:1)

remove-if风格的通用函数:

(defun remove-all (predic seq &optional res)
  (if (null seq)
      (reverse res)
      (cond ((and (not (null (car seq))) (listp (car seq)))
             (remove-all predic (cdr seq)
                         (cons (remove-all predic (car seq)) res)))
            ((funcall predic (car seq))
             (remove-all predic (cdr seq) res))
            (t (remove-all predic (cdr seq) (cons (car seq) res))))))

示例:

>  (remove-all #'null (list 1 2 'nil 3))
=> (1 2 3)
>  (remove-all #'null (list 1 2 'nil '(4 5 nil 6) 3))
=> (1 2 (4 5 6) 3)
>  (remove-all #'(lambda (x) (oddp x)) '(1 2 (3 4) 5 6 (7 8 (9 10))))
=> (2 (4) 6 (8 (10)))

答案 3 :(得分:1)

(defun remove-if-nil (list) (remove-if-not 'identity list))

remove-if-not接受谓词和列表,并删除列表中不满足谓词的所有项,即在谓词中计算时返回nil。正如你所猜测的那样,身份返回完全相同的东西,所以(remove-if-not'身份列表)会删除列表中nil的每个元素。