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



我只被允许使用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))

最新更新