首页 > 解决方案 > 这篇文章如何为给定列表创建所有子列表的列表?

问题描述

有人可以解释一下下面的代码吗?我了解每个小部分的作用,但似乎无法理解它们如何协同工作该功能正在获取一个列表,例如:

(1 2 (3 (4 5) (6 7)) 8 (9 10))

它有 5 个子列表,它返回所有子列表的列表:

((1 2 (3 (4 5) (6 7)) 8 (9 10)) (3 (4 5) (6 7)) (4 5) (6 7) (9 10))

代码是:

(defun all_sublists (l)
    (cond
        ((atom l) nil)
        (T (apply 'append (list l) (mapcar 'all_sublists l)))
    )
)

我知道第一个 cond 说如果 l 是一个原子返回 nil,但你能解释一下第二行是什么吗?为什么我理解的 T 意味着 True,你能尽可能简单地向我解释吗?

标签: lispcommon-lisp

解决方案


all_sublists是一个典型的递归函数。在分析这样的递归函数时,我们可以这样进行:

  1. 查看该函数的实现之前,我们假设它是正确的。那么这个功能有什么作用呢?我们被告知它需要一个包含子列表的列表,并返回一个新列表,其中包含原始列表及其所有子列表的串联(递归,因此如果内部子列表包含其他子列表,则这些子列表与内部子列表一起返回)。所以我们假设这是真的,并查看函数。

  2. 第一行很容易理解:对于空列表,即没有元素的列表,既没有原子也没有子列表,我们返回nil的其实就是列表本身,这符合函数的定义.

  3. 要理解第二行,我们从内部表达式开始。那么,有什么作用(mapcar 'all_sublists l)呢?mapcar返回一个列表,该列表通过将某个函数应用于列表的所有元素的结果连接起来。这里我们应用all_sublists的所有元素l,所以我们返回一个包含所有此类应用结果的列表:换句话说,应用all_sublists到 的每个元素的结果l。当一个元素是一个原子时,它返回nil,而如果一个元素是一个列表,它返回通过将该元素与其所有子列表连接起来获得的列表(我们已经知道all_sublists返回的是什么!)。因此,将返回包含所有这些结果的列表。现在看看外部表达式:(apply 'append (list l) the-result-of-mapcar). apply应用一个函数(在这种情况下append) 到参数列表。因此,在这种情况下,我们将 , 附加到包含原始列表l,作为唯一元素的列表中the-result-of-mapcar。因此,我们获得了一个l由该函数递归生成的列表及其所有子列表。

最后一点:这在某种程度上似乎是“神奇的”,或者可能是“荒谬的”。如果您最初不完全理解它,请不要气馁。我们都有同样的感觉。但是如果你坚持尝试去理解这种递归,你最终会成功!


推荐阅读