Clojure(或任何函数式语言):是否存在通过递归函数构建平面列表的功能方法?

时间:2014-12-18 08:37:24

标签: list recursion clojure flatten

我有一个建立列表的递归函数:

(defn- traverse-dir
  "Traverses the (source) directory, preorder"
  [src-dir dst-root dst-step ffc!]
  (let [{:keys [options]} *parsed-args*
        uname (:unified-name options)
        [dirs files] (list-dir-groomed (fs/list-dir src-dir))

... traverse-dir 的递归调用是 dir-handler

的最后一个表达式
  (doall (concat (map-indexed (dir-handler) dirs) (map-indexed (file-handler) files))))) ;; traverse-dir

traverse-dir 构建的列表是递归的,而我想要一个扁平的列表:

flat-list (->> (flatten recursive-list) (partition 2) (map vec))

首先是否有建立单位清单的方法?没有使用可变列表,即。

1 个答案:

答案 0 :(得分:1)

我不太了解你的上下文,dir-handler没有任何东西,并且返回一个函数,它需要索引和目录,list-dir-groomed以及所有这些,但我' d建议查看tree-seq

(defn tree-seq
  "Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
   branch? must be a fn of one arg that returns true if passed a node
   that can have children (but may not).  children must be a fn of one
   arg that returns a sequence of the children. Will only be called on
   nodes for which branch? returns true. Root is the root node of the
  tree."
  {:added "1.0"
   :static true}
   [branch? children root]
   (let [walk (fn walk [node]
                (lazy-seq
                 (cons node
                  (when (branch? node)
                    (mapcat walk (children node))))))]
     (walk root)))

我在这里使用的是

(tree-seq #(.isDirectory %) #(.listFiles %) (clojure.java.io/as-file file-name))

但你的背景可能意味着不起作用。如果需要清理子文件,可以更改为获取子文件的不同函数,或者只需在输出中使用filter即可。如果这没有好处,那么从节点进入预处理的本地fn的相同​​模式通过递归地映射自己来处理子节点似乎是非常适用的。