2012-11-01 34 views
0

所以我一直在研究lisp中的扁平化列表。lisp中的flatten list

但是,我想要做的是逐層展開列表。

因此而不必

(flatten '(a (b (d (g f))) e)) = (a b d g f e)

我想

(flatten '(a (b (d (g f))) e)) = (a b (d (g f)) e)

如何做到這一點的傢伙你知道嗎?

非常感謝=)

回答

4

你可以做這樣的事情,例如:

(defun fletten-level (tree) 
    (loop for e in tree 
     nconc 
     (if (consp e) 
      (copy-list e) 
      (list e)))) 

(fletten-level '(a (b (d (g f))) e)) 
;; (A B (D (G F)) E) 

這遍歷原樹頂級分支,並創建包含如果分支是一個新的列表葉子,葉子,如果分支有兩個其他分支,那麼第一片葉子和其餘的分支。

編輯:對不起,第一次真的不好,現在應該修好了。

編輯2:只是因爲我幾乎糊塗自己。 (cons (car e) (cdr e))看起來有點不可思議,因爲它基本上只是說e。然而,我意識到nconc將破壞性地修改conses,所以它必須是這樣的(即創建一個新的cons cell來連接而不是重用舊的cell)。編輯3:哇...實際上,它必須是copy-list,因爲它會以這種方式修改原始列表。

3

我的繼承人快速和骯髒的大上無損版本:

(defun flatten-level (tree) 
    (cond ((null tree)()) 
     ((consp (car tree)) (concatenate 'list (car tree) 
             (flatten-level (cdr tree)))) 
     (t (cons (car tree) (flatten-level (cdr tree)))))) 

這是走的樹,併爲每個元素,如果它加到它到cons'ed元素的遞歸函數樹的其餘部分變平。

+1

其他答案中的版本也是非破壞性的;它使用'nconc'作爲實現工具,但它只會改變剛分配'list'或'copy-list'的結構。因此,它以自頂向下的方式構建其結果,無需額外的「考慮」或遞歸,因此效率很高。這就是你的代碼([「尾遞歸模反作弊」](http://en.wikipedia.org/wiki/Tail_call#Tail_recursion_modulo_cons))可以被實現TRMC的系統合理*編譯*爲(或自動重寫)優化。 –

+0

啊,是的,這是有道理的。謝謝你解釋! – user1582220