2017-03-29 36 views
0

我必須在lisp中做一個遞歸函數,它需要一個列表,並在給定列表中只有奇數位置的元素生成另一個列表。如何使用Lisp中的迭代函數在列表中的奇數位置打印元素?

如果我有(1 2 3 4 5)我要輸出(1 3 5)

我這裏有一個代碼:

(defun pozpar(lst) (do(
(l lst (cddr l)) 
(x '() (cons x (car l)))) 
((null l) x))) 

此輸出:

(5 3 1) 

我知道cons在開始添加元素我嘗試了appendlist,但沒有任何工作。

+0

有很多Lisps。看起來你在這裏使用的是Common Lisp,所以我建議爲你使用的特定的* Lisp添加一個標籤。 –

+0

這看起來不像*遞歸*函數。沒有使用遞歸。 –

回答

1

最簡單的方法是reverse結果:

(defun pozpar (lst) 
    (do ((l lst (cddr l)) 
     (x '() (cons (car l) x))) 
     ((null l) 
     (nreverse x)))) 

(pozpar '(1 2 3 4 5)) 
==> (1 3 5) 

  1. 回報,不輸出你想要的值。

  2. 預先設置值和恢復結果是一種常見的Lisp編碼模式。

  3. 由於append線性在其參數的長度,在一個循環中利用它產生二次代碼。

  4. 我在standard Lisp way中格式化了代碼。如果你使用這種風格,lispers會更容易閱讀你的代碼,因此更願意幫助你。

1

對於使用loop它很容易讓你處理的順序的元素。這也是最有效的,也是唯一一個保證所有長度參數的工作:

(defun pozpar1 (lst) 
    (loop :for e :in lst :by #'cddr 
     :collect e))) 

如果你真的想遞歸我會用蓄電池與中端線性更新反向做到了:

(defun pozpar2 (lst) 
    (labels ((helper (lst acc) 
      (if (endp lst) 
       (nreverse acc) 
       (helper (cddr lst) (cons (car lst) acc))))) 
    (helper lst '()))) 

但是經典的不是尾遞歸的版本是這樣的:

(defun pozpar3 (lst) 
    (if (endp lst) 
     '() 
     (cons (car lst) (pozpar3 (cddr lst))))) 
0

我覺得這是一種簡單的解決方案:

(defun popzar (lst) 
    (cond 
    ((null lst) nil) 
    (t (cons (car lst) (popzar (cdr (cdr lst))))) 
)) 

它首先檢查該列表爲空,如果不是它創建的第一個元素,並與名單的除了第二個元素,其餘再次調用本身的結果,一個新的列表。

相關問題