2012-11-01 35 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