List 用于确定列表中嵌套列表长度的公共Lisp函数

List 用于确定列表中嵌套列表长度的公共Lisp函数,list,lisp,common-lisp,nested-lists,do-loops,List,Lisp,Common Lisp,Nested Lists,Do Loops,我只允许使用doconstruct,这一概念我还没有掌握。我尝试了以下代码,但它返回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
construct,这一概念我还没有掌握。我尝试了以下代码,但它返回
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,即它将丢失其第一个元素。 结束条件还包括函数的返回值。对于
((null l)(nreverse result))
我们说,当变量
l
为null时,函数将结束并返回值
(nreverse result)
。为什么要用nreverse?因为我们在体内使用推力,它以错误的顺序累积值。
最后,正文告诉函数在
结果中添加
l
的第一个元素的长度,只要这是一个列表。

迭代
嵌套列表中的所有项。根据
listp
,计算每个列表的长度并收集。收集的长度列表是结果值:

(loop for item in nested-list
      if (listp item) collect (length item))
将每个元素
嵌套列表
传递到函数中。对于列表中的每个项目,函数返回长度为一个元素的列表,否则返回空列表。这些列表被链接成一个列表,并返回

(mapcan (lambda (x) (if (listp x) (list (length x)))) nested-list)
从嵌套列表中删除非列表项,生成仅包含列表的新列表。然后通过
length
函数映射此列表,生成一个长度列表:

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

不,
(fun'(a(b)(c d))
返回
(1 2)
DO
不是一个函数,而是一个特殊的操作符。添加一些关于它们如何工作以及为什么工作的解释几乎总是可以改进代码的答案?打字-如果(lisp项)应该是如果(listp项)?@SurajKumar这里没有特殊的技巧或算法;一些库功能(已完全记录)正在以基本方式使用。如果有人不打算自己做家庭作业,他们至少应该自己研究填鸭式解决方案是如何工作的(以防他们被要求向教授解释他们的意见)。@Kaz Code-only答案可能会解决问题,但如果你解释他们是如何解决问题的,那么答案会更有用。社区需要理论和代码来充分理解您的答案。这就是你的答案出现在评论中的原因。@SurajKumar我会试试。