我只被允许使用do
构造,但我仍然无法理解这个概念。我尝试了以下代码,但它返回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
为空时,函数将结束并返回值(nreverse result)
。为什么是反转录?因为我们在体内使用推力,这会以错误的顺序累积值。最后,当l
的第一个元素是列表时,主体告诉函数将其长度添加到result
。
遍历nested-list
中的所有项。对于根据listp
的每个列表,计算长度并收集它。收集的长度列表是结果值:
(loop for item in nested-list
if (listp item) collect (length item))
将每个元素nested-list
传递到一个函数中。对于作为列表的每个项,函数返回一个长度为的单元素列表,否则返回空列表。这些列表被连接起来形成一个列表,并返回。
(mapcan (lambda (x) (if (listp x) (list (length x)))) nested-list)
从nested-list
中删除非列表项,生成一个只有列表的新列表。然后通过length
函数映射该列表,得到一个长度列表:
(mapcar #'length (remove-if-not #'listp nested-list))