Функция LISP для удаления nils - PullRequest
4 голосов
/ 19 октября 2010

Я хочу написать функцию в LISP, которая полностью удалит все NILS в списке. Список может быть вложенным, то есть он может содержать другие списки внутри. Например, список '((состояние L L L L) NIL (состояние L L R L) NIL) должен быть преобразован в' ((СОСТОЯНИЕ L L L L) (СОСТОЯНИЕ L L R L)).

Ответы [ 4 ]

10 голосов
/ 19 октября 2010
(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))
3 голосов
/ 23 октября 2010

Пол Грэм называет эту функцию (повторяющуюся в подсписках remove-if) "обрезать" в На Лиспе , с.49. Это одна из служебных функций.

(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))
1 голос
/ 10 сентября 2014
(defun remove-if-nil (list) (remove-if-not 'identity list))

remove-if-not принимает предикат и список и удаляет все элементы в списке, которые не удовлетворяют предикату, то есть возвращают ноль при оценке в предикате. идентичность, как вы можете догадаться, возвращает точно то же самое, что и она, поэтому (удалить-если-не 'список идентичности) удаляет каждый элемент в списке, который равен nil.

1 голос
/ 20 октября 2010

Универсальная функция в стиле 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)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...