从非线性列表

时间:2017-01-02 15:04:55

标签: recursion common-lisp

我试图从列表的任何级别删除列表中所有出现的元素。 我需要使用地图功能。我正在使用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))

我希望我的问题形成得很好并且足够详细,我正在提供工作实例。有人可以给我一些关于如何解决这个问题的提示吗?

1 个答案:

答案 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我已重命名该函数,因为deleteremove的破坏性版本。我还保留了standard functions

的参数顺序