Lisp:从给定列表中删除所有 a 和 return 非 a 值

Lisp: remove all a's from a given list and return non-a values

我尝试 return 列表中与“a”不匹配的每个元素。 这是我到目前为止尝试过的方法。

(defun removeA (arr) 
     (cond((null arr) nil) 
          ((if (listp (car arr))
               (or (removeA (car arr)) (removeA (cdr arr)))
          (if (eql 'a (car arr))      
              (removeA (cdr arr)) 
          (cons (car arr) (removeA (cdr arr)))
)
))
)

) (print (removeA '(a (a) (v a e) (a a) d)))

here is the output: (V E)

i need help on why its not printing "D" as well

程序的规范似乎是这样的:

  • 输入是单个项目或列表的列表
  • 如果是单个项目,如果它的值是 'a'
  • ,则将其删除
  • 如果是列表,删除其中所有值为 'a'
  • 的项目

我的第一反应是在输入列表上映射一个函数,使用 mapcar 或类似的东西 - 如果您使用 carcdr 则值得检查一下是否有是做同样事情的更高层次的方法。

不过,我被告知使用mapcar效率低下,更好的方法是使用looploop结构是一个宏,在函数位置有loop,后面跟着一串英语风格的单词。

(defun remove-a (lst)
  (loop
   for x in lst
   if (listp x) collect (remove-if #'isa-p x)
   else collect (if (isa-p x) nil x)))

(defun isa-p (val) (equal val 'a))

因此:

(remove-a  '(a (a) (v a e) (a a) d))
(NIL NIL (V E) NIL D)

可以使用 Alexandria:flatten 将结果展平为单个列表,您需要先使用 (ql:quicklisp 'Alexandria) 加载它。

如果要用carcdr,我的意见如下

您作为输入提供的是一个列表,但您称它为 arr,建议使用数组;数组在 Common Lisp 中是非常不同的东西。

您的 ifcond 搞错了。函数 cond 类似于其他语言中的 switch-case。在考虑 cond.

的各种可能性之前,您想使用 if 检查空列表

您正在使用 print 来显示结果。如果您使用的是 REPL,则不需要这样做。 (print a)a 在 REPL 中是等价的。

我的解决方案:

(defun removeA (ls)
  (let ((withoutA
          (if (consp ls)
            (remove-if #'(lambda (l) (equal l 'a)) ls)
            ls)))
    (if (consp ls)
      (mapcar #'removeA withoutA)
      ls)))

(print
  (removeA '(a (a) (v a e) (a a) d)))

打印 (NIL (V E) NIL D).

NIL代表空列表。