2009-09-14 61 views
2

如何顛倒一個列表,使每個子列表也被顛倒?這是我到目前爲止有: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)))))) 

回答

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

短一點: (defun定義我的反轉(L)(我的反向(cdr l)) (list(if(listp(car l))(my-reverse(car l))(car l))))) ) – jlf 2009-09-14 23:59:57

0

聽起來像一個家庭作業問題:)

看起來你寫的常規反向代碼開始。我會給你一個提示:第二個條件(listp L)不是很對(它永遠是真的)。你想要檢查是否有其他東西是一個列表。

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))) 
0

dmitry_vk的回答(這可能是在大多數的Lisp比使用附加在前面的例子更快)更lispish方式:

(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))))