用于确定列表中嵌套列表长度的 Common Lisp 函数

Common Lisp function to determine lengths of nested lists in a list

我只被允许使用 do 构造,我仍然无法理解的概念。我尝试了以下代码,但它 returns nil.

(defun fun(list)
(do ((i 0 (+ i 1)) (l '() (if (listp (nth i list)) (append l (list (length (nth i list)))))))
((null (nth i list)) l)
)
)

l的更新值有误吗?此列表 (a (b) (c d)) 的输出应为 (1 2)

尝试用列表而不是数组来思考。您正在使用列表的第 n 个元素,就好像它是一个数组一样。相反,使用 do 您可以通过每次获取下一个子列表来遍历列表,即删除第一个元素并获取另一个没有第一个元素的列表。

(defun fun(list)
  (do ((l list (cdr l))
       (result nil) )
      ((null l) (nreverse result))
    (if (listp (car l))
      (push (length (car l)) result) )))

do 运算符采用三个参数:变量列表、结束条件和循环体。第一个包括变量的名称、它们的初始值以及(可选)它们如何从一个循环变为下一个循环。例如,(l list (cdr l)) 表示您使用一个变量 l,其初始值为输入列表,并且从一个循环到下一个循环它将成为其自身的 cdr,即它将丢失其第一个元素。 结束条件还包括函数的 return 值。使用 ((null l) (nreverse result)) 我们是说当变量 l 为 null 时,函数将结束并且 return 值为 (nreverse result)。为什么不反转?因为我们在 body 中使用了 push,它以错误的顺序累积值。 最后,当这是一个列表时,正文告诉函数将 l 的第一个元素的长度添加到 result

遍历 nested-list 中的所有项目。对每一个按照listp为list的,计算长度,收集起来。收集到的长度列表就是结果值:

(loop for item in nested-list
      if (listp item) collect (length item))

将每个元素 nested-list 传递到一个函数中。对于列表中的每个项目,函数 returns 一个长度的单元素列表,否则它 returns 空列表。这些列表被串联成一个列表,并返回。

(mapcan (lambda (x) (if (listp x) (list (length x)))) nested-list)

nested-list 中删除非列表项,生成一个只有列表的新列表。然后通过length函数映射这个列表,得到长度列表:

(mapcar #'length (remove-if-not #'listp nested-list))