首页 > 代码库 > clojure产生具有parent-id的样例数据。(恳请提供更好的思路)
clojure产生具有parent-id的样例数据。(恳请提供更好的思路)
为了测试,我需要类似下面的数据:
{:id 55 :parent_id nil} {:id 104 :parent_id 55}
最终函数可以指定层数和每个分支的个数,比如2层10个,总共110,3层10个1110,4层10个11110等等。
我整整花了2个白天时间,总算写了出来,当然中间顺带练习了一下macro。有两个版本,一个是macro版本,一个是iterate版本,当然后者应该是正解。
为了减少macro代码的复杂度,先写了一个子函数。
(defn- create-children [parentv n] (flatten (map (fn [pnd] (take n (map (fn [id] {:id id, :parent_id (:id pnd)}) (repeatedly get-next)))) parentv)))
中间的map生成一个条目的n个儿子,外网的map根据传递过来的父节点的集合,对每个父节点生成n个儿子。生成:
( (10个儿子) (10个儿子) (10个儿子)),这样的结构。最后flatten扁平化成一个集合。
接下来是函数的实现:
macro版本:
(defmacro tree-items [lev n] (let [llls (let [levs (map #(symbol (str "i" %)) (rest (range lev))) levs1 (map #(symbol (str "i" %)) (drop-last (range lev))) ctpl ‘(create-children x y) tpl-seq (map #(vector %1 (template/apply-template ‘[x y] ctpl [%2 n])) levs levs1)] (vec (apply concat tpl-seq))) lresult (vec (map #(symbol (str "i" %)) (rest (range lev)))) scaffold (template/apply-template ‘[x llls lresult] ‘(let [i0 (take x (map #(assoc {:parent_id nil} :id %) (repeatedly get-next))) levels (let llls lresult)] (flatten [i0 levels])) [n llls lresult])]
所谓macro,就是用程序写程序,执行macro的结果是程序代码,然后再执行生成的代码。可以用macroexpand来查看生成的程序的结果。
(let* [i0 (take 10 (map (fn* [p1__60273#] (assoc {:parent_id nil} :id p1__60273#)) (repeatedly get-next))) levels (let [i1 (create-children i0 10) i2 (create-children i1 10) i3 (create-children i2 10) i4 (create-children i3 10)] [i1 i2 i3 i4])] (flatten [i0 levels]))
当然写macro比较杀脑细胞。
iterate版本:
(defn tree-items-i [lev n] (let [lev (dec lev) rootn (take n (map #(assoc {:parent_id nil} :id %) (repeatedly get-next)))] (flatten (take lev (iterate #(create-children % n) rootn)))))
代码明显简单多了。
总结:
clojure的一些产生无限序列的函数或者macro需要多加练习才能领悟。
有时候当局者迷,也许你看了这个代码会觉得很好笑,因为你知道更方便的写法。如果这样,请告诉我。
clojure产生具有parent-id的样例数据。(恳请提供更好的思路)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。