我试图从列表的任何级别删除列表中所有出现的元素。 我需要使用地图功能。我正在使用Common Lisp。例如,我希望能够做到:
(fdelete '(1 2 3 4 (3)) 3) => (1 2 4)
到目前为止我尝试过的事情: 这个功能可以满足你的需要。它将用NIL替换给定元素的所有出现,因此它不完全是我想要的。
(defun fdelete (l e)
(cond
((null l) 0)
((equal l e) nil)
((atom l) l)
(t (mapcar (lambda(l) (fdelete l e )) l ))
)
)
这样做
(fdelete '(1 2 3 4 (3)) 3) => (1 2 NIL 4 (NIL))
我的第二次尝试是使用mapcap函数,因为这个函数不会返回与输入列表大小相同的列表。 这将做所需要的,但它会摧毁'我的初始列表,如同在,它将使所有子列表浮出水面'。
(defun fdelete (l e)
(cond
((null l) 0)
((equal l e) nil)
((atom l) (list l))
(t(mapcan(lambda(x) (fdelete x e ))l ))
)
)
所以这确实(fdelete '(1 2 3 4 (3)) 3) => (1 2 4)
但如果我试着这样做也会做错:
(fdelete '(1 2 3 (4) (3)) 3)) => (1 2 4)
我希望它能(fdelete '(1 2 3 (4) (3)) 3)) => (1 2 (4))
我希望我的问题形成得很好并且足够详细,我正在提供工作实例。有人可以给我一些关于如何解决这个问题的提示吗?
答案 0 :(得分:2)
使用mapcan
是正确的选择,因为您可以包含list
来获取值或使用nil
来删除项目。对于list元素,如果它不匹配要删除的内容,则应该检查递归的结果,如果它不是空列表,则将其包装。
解决方案看起来像:
(defun remove-deep (item list)
(mapcan (lambda (cur)
(cond ((equal item cur) '())
...))
list))
(remove-deep 3 '(1 nil 2 3 (3) (3 4)))
; ==> (1 nil 2 (4))
要应用principle of least surprise我已重命名该函数,因为delete
是remove
的破坏性版本。我还保留了standard functions: