0

所以我一直在研究在 lisp 中展平列表。

但是,我想做的是逐级展平列表。

所以而不是拥有

(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

2 回答 2

5

你可以做这样的事情,例如:

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

这会遍历原始树的顶级分支并创建一个新列表,其中包含该分支是否为叶子,该叶子,如果该分支有两个其他分支,则包含第一个叶子和其余分支。

编辑:对不起,实际上第一次并不好,现在应该修复它。

EDIT2:只是因为我自己几乎都糊涂了。(cons (car e) (cdr e))看起来有点奇怪,因为它基本上与说 just 相同e。然而,我意识到这nconc会破坏性地修改 conses,所以它必须是这种方式(即创建一个新的 cons 单元以连接而不是重用旧单元)。

EDIT3:哇...实际上,它必须是copy-list,因为它会以这种方式修改原始列表。

于 2012-11-01T08:24:31.290 回答
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 元素,它将把它连接到树的其余部分,展平。

于 2012-11-01T19:25:55.980 回答