【问题标题】:Delete occurences of item from non-linear list从非线性列表中删除项目的出现
【发布时间】:2017-01-02 15:04:55
【问题描述】:

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

我希望我的问题结构良好且足够详细,并且我正在提供工作示例。有人能给我一些关于如何解决这个问题的提示吗?

【问题讨论】:

  • reduce 被认为是“地图功能”吗?
  • 不,问题表明我必须使用 mapcon、mapcan、mapcar 或 maplist。顺便说一句,这不是家庭作业,我只是在为即将到来的考试练习。
  • 真的应该是(fdelete '(1 2 3 4 (3)) 3) => (1 2 4 ()),因为(fdelete '(3) 3) => ()

标签: recursion common-lisp


【解决方案1】:

使用mapcan 是正确的选择,因为您可以使用list 来获取值或使用nil 来移除项目。对于列表元素,如果它与要删除的内容不匹配,则应检查递归结果,如果它不是空列表,则将其包装。

解决方案类似于:

(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 的参数顺序:

【讨论】:

  • {3 (3)} ==> () 因此它必须是{3 (1 3 (3))} ==> (1 ())
  • @WillNess 我同意消除空列表以及item 是非常规的。如果不看规范,我会期望我的测试结果是(1 nil 2 nil (4)),这更简单,因为你只是包装了递归,但是 OP 指定也省略像我的测试中一样变为空的列表。
  • 是的,我认为他们错了。我使用简单的英语,并且一致性:从 (1 3) 中删除 3 给我们 (1),因此从 (3) -- (),因此从 (1 3 (3)) 中删除 3 必须给我们 (1 () )。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 2022-12-20
  • 1970-01-01
  • 2016-05-08
  • 2011-03-18
相关资源
最近更新 更多