简体   繁体   English

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

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

I am only allowed to use the do construct, concept which i still can't get a grasp of.我只被允许使用do构造,我仍然无法掌握的概念。 I tried the following code, but it returns nil .我尝试了以下代码,但它返回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)
)
)

Is the updated value of l wrong? l的更新值是错误的吗? The output for this list (a (b) (cd)) should be (1 2) .此列表的输出(a (b) (cd))应为(1 2)

Try to think in terms of lists instead of arrays.试着用列表而不是数组来思考。 You are using the n-th element of a list as if it was an array.您正在使用列表的第 n 个元素,就好像它是一个数组一样。 Instead, with do you can traverse the list by taking the next sublist each time, ie dropping the first element and getting another list without that first element.相反,用do您可以通过采取下一子列表每次,即下降的第一个元素并得到另一个列表,而这第一个元素遍历列表。

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

The do operator takes three arguments: the list of variables, the end condition and the body of the loop. do运算符接受三个参数:变量列表、结束条件和循环体。 The first includes the name of the variables, their initial value and (optionally) how they change from one loop to the next.第一个包括变量的名称、它们的初始值以及(可选)它们如何从一个循环更改为下一个循环。 For example, (l list (cdr l)) says that you use a variable l whose initial value is the input list and from one loop to the next it will become the cdr of itself, ie it will lose its first element.例如, (l list (cdr l))表示你使用一个变量l它的初始值是输入列表,从一个循环到下一个循环,它将成为它自己的 cdr,即它会丢失它的第一个元素。 The ending condition includes also the return value of the function.结束条件还包括函数的返回值。 With ((null l) (nreverse result)) we are saying that when the variable l is null, the function will end and return the value (nreverse result) .使用((null l) (nreverse result))我们是说当变量l为空时,函数将结束并返回值(nreverse result) Why nreverse?为什么要逆向? Because we use push in the body, which accumulates values in the wrong order.因为我们在 body 中使用 push,它以错误的顺序累积值。 Finally, the body tells the function to add to result the length of the first element of l whenever this is a list.最后,主体告诉函数将l的第一个元素的长度添加到result ,只要这是一个列表。

Iterate over all the items in nested-list .迭代nested-list所有项目。 For each one that is a list according to listp , calculate the length and collect it.对于根据listp是列表的每个,计算长度并收集它。 The list of collected lengths is the resulting value:收集的长度列表是结果值:

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

Pass each element nested-list into a function.将每个元素nested-list传递给一个函数。 For each item which is a list, the function returns a one-element list of the length, otherwise it returns the empty list.对于列表中的每一项,该函数返回一个长度的单元素列表,否则返回空列表。 The lists are catenated to form one list, and returned.这些列表被连接起来形成一个列表,然后返回。

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

Remove non-list items from nested-list , producing a new list which has only lists.nested-list删除非列表项,生成一个只有列表的新列表。 Then map this list through the length function, resulting in a list of lengths:然后通过length函数映射这个列表,得到一个长度列表:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM