LISP:多级递归反向函数

时间:2009-09-14 16:56:23

标签: list recursion lisp

如何反转列表以使每个子列表也被反转?这就是我到目前为止所做的:

(defun REV (L)
  (cond
    ((null L) nil)
    ((listp L)
     (append
      (REV (cdr L))
      (list (car L))))
    (t
     (append
      (REV (cdr L)) 
      (list (car L))))))

4 个答案:

答案 0 :(得分:5)

你走在正确的轨道上,但是你的最后两个条件具有相同的动作,这应该表明其中一个没有做它应该做的事情。实际上,第二个条件listp不正确,因为当它是一个列表时,你需要附加该列表的反向而不是未修改的列表。一个可能的解决方案:

(defun reverse (l)
  (cond ((null? l) nil)
        ((listp (car l)) (append (reverse (cdr l)) 
                                 (list (reverse (car l)))))
        (t
          (append (reverse (cdr l)) 
                  (list (car l))))))

>  (reverse '((1 2 3) (4 5 6)))
((6 5 4) (3 2 1))

正如您所看到的,唯一的区别是您测试第一个元素是否为列表,如果是,则在追加第一个元素之前将其反转。

答案 1 :(得分:2)

我会这样写:

(defun reverse-all (list)
  (loop
     with result = nil
     for element in list
     if (listp element)
     do (push (reverse-all element) result)
     else do (push element result)
     finally (return result)))

答案 2 :(得分:0)

听起来像是一个家庭作业问题:)

看起来你是通过编写常规反向代码开始的。我会给你一个提示:第二个条件(listp L)不太正确(它总是如此)。你想检查是否有其他东西是列表。

答案 3 :(得分:0)

dmitry_vk的答案(在大多数lisps中可能比在前面的例子中使用append更快)以更加低调的方式:

(defun reverse-all (list)
  (let ((result nil))
    (dolist (element list result)
      (if (listp element)
          (push (reverse-all element) result)
          (push element result)))))

甚至:

(defun reverse-all (list)
  (let ((result nil))
    (dolist (element list result)
      (push
        (if (listp element) (reverse-all element) element)
          result))))