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
或类似的东西 - 如果您使用 car
或 cdr
则值得检查一下是否有是做同样事情的更高层次的方法。
不过,我被告知使用mapcar
效率低下,更好的方法是使用loop
。 loop
结构是一个宏,在函数位置有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)
加载它。
如果要用car
和cdr
,我的意见如下
您作为输入提供的是一个列表,但您称它为 arr
,建议使用数组;数组在 Common Lisp 中是非常不同的东西。
您的 if
和 cond
搞错了。函数 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
代表空列表。
我尝试 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
或类似的东西 - 如果您使用 car
或 cdr
则值得检查一下是否有是做同样事情的更高层次的方法。
不过,我被告知使用mapcar
效率低下,更好的方法是使用loop
。 loop
结构是一个宏,在函数位置有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)
加载它。
如果要用car
和cdr
,我的意见如下
您作为输入提供的是一个列表,但您称它为 arr
,建议使用数组;数组在 Common Lisp 中是非常不同的东西。
您的 if
和 cond
搞错了。函数 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
代表空列表。