通过嵌套列表LISP递归

时间:2013-03-12 01:58:35

标签: lisp common-lisp

我如何通过嵌套列表进行递归?

例如,给定:'((A 1 2) (B 3 4))

如何将2添加到每个嵌套子列表中的第二个元素?

(defun get-p0 (points)
    (loop for x from 0 to
            (-  (list-length    points) 1) do
                (+ 2 (cadr (nth x points)))
    )
)

我不确定为什么(get-p0 '((A 1 2) (B 3 4)))会返回NIL。

4 个答案:

答案 0 :(得分:3)

我会选择这样的事情:

(loop for (letter x y) in '((A 1 2) (B 3 4))
     collect (list letter (+ 2 x) y))

原因:它更短,你不测量列表的长度以便迭代它(为什么你会这样做?)

答案 1 :(得分:2)

因为你要求递归解决方案:

(defun get-p0 (lst &optional (n 0))
  (if (null lst) 
      nil
      (let ((elt1 (first lst)) (eltn (cdr lst)))
        (if (listp elt1)
             (cons (get-p0 elt1) (get-p0 eltn))
             (cons (if (= n 1) (+ elt1 2) elt1) (get-p0 eltn (+ n 1)))))))

所以

? (get-p0 '((A 1 2) (B 3 4)))
((A 3 2) (B 5 4))

如果有必要,它会进一步减少:

? (get-p0 '((A 0 2) ((B -4 4) (C 10 4))))
((A 2 2) ((B -2 4) (C 12 4)))

答案 2 :(得分:1)

你提出它的方式,你可以把问题看作一个基本的递归模式:你使用递归或迭代(mapcarreduce等等来查看列表; dolistloop等)并将函数应用于其条目。这是一个功能性解决方案:

(defun get-p0 (points)
  (mapcar #'add-2 points))

其中辅助功能可以定义如下:

(defun add-2 (lst)
  "Add 2 to the 2nd item"
  (let ((res '()))
    (do ((l lst (cdr l))
         (i 1 (1+ i)))
      ((null l) (nreverse res))
      (push (if (= 2 i)
              (+ 2 (car l))
              (car l))
            res))))

答案 3 :(得分:0)

如你所写的“循环”使用不会返回任何内容;因此返回NIL。因为你的代码只是迭代x并计算某些东西;某些东西没有储存在任何地方。

那么,如何获得理想的结果呢?假设您愿意修改点中的每个点,这应该有效:

(defun get-p0 (points)
  (loop for x from 0 to (- (list-length points) 1) do
    (let ((point (nth x points)))
      (setf (cadr point) (+ 2 (cadr point)))))
   points)