Как удалить список длины 1 из вложенного списка в lisp? - PullRequest
1 голос
/ 29 февраля 2020

У меня есть вложенный список (1 (4 (5) 3) 9 10), и я хочу удалить списки длиной 1, чтобы результат был (1 (4 3) 9 10). Это то, что я пробовал до сих пор, который не удаляет (5) и возвращает исходный список.

(defun remove (l)
(cond
    ((null l) nil)   
    ((and (listp (car l)) (= (length l) 1)) (remove (cdr l)))   
    ((atom (car l)) (cons (car l) (remove (cdr l))))
    (T (cons (remove (car l)) (remove (cdr l))))   
))

Ответы [ 2 ]

2 голосов
/ 29 февраля 2020

Две вещи: во-первых, remove - это предопределенная функция в пакете CL, поэтому я настоятельно рекомендую использовать другое имя, скажем, my-remove. Во-вторых, вы тестируете длину l вместо подсписка (car l), который вы хотите исключить. Правильная форма будет:

(defun my-remove (l)
  (cond
    ((null l) nil)   
    ((and (listp (car l)) (= (length (car l)) 1)) (my-remove (cdr l)))   
    ((atom (car l)) (cons (car l) (my-remove (cdr l))))
    (T (cons (my-remove (car l)) (my-remove (cdr l))))   
))
0 голосов
/ 29 февраля 2020

Хвост рекурсивная версия. Плюс: без теста (atom (car l)) быть разрешающим для не-списочных и неатомных компонентов в списке. (например, векторы или другие объекты в качестве элемента списка - они рассматриваются как атомы.

(defun my-remove (l &optional (acc '()))
  (cond ((null l) (nreverse acc))
        ((listp (car l)) (if (= 1 (length (car l)))         ;; list objects
                             (my-remove (cdr l) acc)        ;; - of length 1     
                             (my-remove (cdr l) (cons (my-remove (car l)) acc)))) ;; - longer
        (t (my-remove (cdr l) (cons (car l) acc)))))        ;; non-list objects
...