【问题标题】:How can I save the result of a dolist in a new list?如何将 dolist 的结果保存在新列表中?
【发布时间】:2017-06-28 21:09:39
【问题描述】:

我想用两个给定的列表删除不在两个列表中的元素。

我正在尝试的代码是:

(defun remove_odd_ones(L1 L2)
    (cond ((or (null L1) (null L2)) nil)
           ((dolist (x L2) (if (not(member x L1)) (remove x L2))))))


(remove_odd_ones '(a b c c e k) '(a b c p d d n))

我的期待:(a b c c)

我收到的结果:NIL

知道我可以使用什么函数将dolist 结果保存到新列表中吗?

【问题讨论】:

  • remove 表示从其他东西中删除某些东西,但是从您的描述从您的示例中,您不清楚您的任务是什么需要解决。您想生成两个列表中都存在的元素吗?但是,为什么k 不存在于结果中,而d 存在?它们都只在一个列表中。
  • 你说得对,我确实打错了 ir。预期的结果将只是 (a b c)。也就是说,属于 L2 的元素也会出现在 L1 中。
  • 你不是说这两个集合的交集吗?这是 CL 当然有一个功能。但是,请注意,由于您的列表中有重复项,您将在结果中得到重复项。还有一个函数可以处理这个问题。如果这是家庭作业并且您必须使用 dolist 编写函数,那么 dolist 的语法是 (dolist ( var list [result-form]) statements)。在 CLHS 中查找示例 dolist lispworks.com/documentation/HyperSpec/Body/m_dolist.htm
  • 实际上,我需要保留重复项,所以'intersect' 函数对我来说是完美的,非常感谢。
  • 显示的结果(a b c d d)是打字错误,我期待的结果真的是(a b c c),我现在编辑了这个问题,以防止更多的错误。关于函数:正如 David Hodge 所建议的那样,“intersection”函数正是我想知道的,我在代码中使用了这里并得到了我想要的所有结果。非常感谢大家。

标签: lisp common-lisp


【解决方案1】:

(remove_odd_ones '(a b c c e k) '(a b c p d d n))

我的期望:(a b c c)

这就是所谓的“设置交点”:

Lisp> (intersection '(a b c c e k) '(a b c p d d n))
(A B C C)

我们自己如何(低效地)做到这一点是:

(defun our-intersection (l1 l2)
  (mapcan (lambda (l1-item)
            (if (member l1-item l2)
              (list l1-item)))
          l1))

映射l1,收集l2中的元素。

dolist 函数不适合这个,因为它不是功能/应用程序;这是一个命令式循环小工具。如果您想使用dolist 收集结果列表,您必须自己通过主体中的操作来完成,并借助其他变量:

(defun our-intersection (l1 l2)
  (let ((out nil))
    (dolist (l1-item l1 out)
      (when (member l1-item l2)
        (push l1-item out)))))

我们定义了一个变量out,它最初保存的是空列表。我们的dolist 遍历l1,依次为每个元素设置变量l1-item。如果l1-item 出现在l2 中,则将其推送到out 列表中:

Lisp> (our-intersection '(a b c c e k) '(a b c p d d n))
(C C B A)

dolist 至少让我们通过它的第三个参数来指定将产生表单结果值的表达式:这就是我们放置对out 的引用的地方。

要以(A B C C) 的顺序获取它,我们可以用nreverse 调用替换该引用,如下所示:

(dolist (l1-item l1 (nreverse out))
  ... )

这是 Common Lisp 列表过程编程中的常见模式:通过推送到新的本地列表来累积结果,然后在返回之前使用 nreverse 破坏性地反转它。 (这是安全的,因为该列表是由程序代码在本地分配的:在返回 is 之前,程序中的任何其他内容都不知道该列表,因此破坏性的重新排列不会影响任何其他函数或模块。

【讨论】:

    猜你喜欢
    • 2022-08-11
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    相关资源
    最近更新 更多