所以我有一个用于评论的数据库表,我学会了如何使用WITH RECURSIVE
作为树来返回主题的所有评论。但是,因为它的SQL,它只是作为列表返回。
当我执行查询时,这些是我得到的结果(级别不是表格中的列,它是在查询结果时由查询计算的):
[
{
:id "1"
:parent_id nil,
:content "This is another top-level comment",
:level "1",
:rating 0,
}
{
:id "2"
:parent_id "1",
:content "What a comment!",
:level "1 -> 2",
:rating 0,
}
{
:id "4"
:parent_id "2",
:content "Trying to see how trees work",
:level "1 -> 2 -> 4",
:rating 0,
}
{
:id "3"
:parent_id "2",
:content "No idea how this will turn out",
:level "1 -> 2 -> 3",
:rating 0,
}
{
:id "5"
:parent_id nil,
:content "This is a top-level comment",
:level "5",
:rating 0,
}
{
:id "9"
:parent_id "5",
:content "This is yet another testing comment",
:level "5 -> 9",
:rating 0,
}
{
:id "8"
:parent_id "7",
:content "It sure is!",
:level "5 -> 7 -> 8",
:rating 0,
}
{
:id "7"
:parent_id "5",
:content "This!",
:level "5 -> 7",
:rating 0,
}
{
:id "6"
:parent_id "5",
:content "Hey look at me",
:level "5 -> 6",
:rating 0,
}
]
我想知道的是如何翻转多棵树,以便我最终得到这样的结果:
1 'This is another top-level comment'
↳ 2 'What a comment!'
↳ 4 'Trying to see how trees work'
↳ 3 'No idea how this will turn out'
5 'This is a top-level comment'
↳ 9 'This is yet another testing comment'
↳ 7 'This!'
↳ 8 'It sure is!'
↳ 6 'Hey look at me'
使用此函数只能获取第一个树(根节点为id 1的树):
(defn make-tree
([coll] (let [root (first (remove :parent coll))]
{:node root :children (make-tree root coll)}))
([root coll]
(for [x coll :when (= (:parent_id x) (:id root))]
{:node x :children (make-tree x coll)})))
关于如何修改该功能或更改我传入的内容以便最终得到多个树的任何想法或提示?
答案 0 :(得分:0)
你可以定义一个make-trees函数:
(defn make-trees [id coll]
(map
(fn [node] {:node node :children (make-trees (node :id) coll)})
(filter #(= (% :parent_id) id) coll)))
这样叫:
(make-trees nil YOUR_COLL)
答案 1 :(得分:0)
如果您可以依赖:level
条目,则可以将其作为与assoc-in
一起使用的密钥序列的来源。然后,您可以使用reduce
和assoc-in
上构建的小lambda,使用专用根节点提及@coredump方法:
(defn- key-seq [comment]
(->> comment
:level
(re-seq (re-pattern "\\d+"))
(interpose :children)))
(defn list->forest [comments]
(vals (reduce (fn [root comment]
(assoc-in root (key-seq comment) {:node comment :children {}}))
{}
comments)))
我在vals
的结果上使用reduce
再次丢弃外部根图,但这有点可选。
如果你想要使用它的真实数据实际上在:level
中有UUID,那么我们需要使用更合适的正则表达式。以上将把任何十进制数字部分视为ID。 Using these answers我们可以收集:level
字符串中的所有UUID。
我reworked your example data使用一些随机UUID代替您提供的数字。从上面的链接使用Gajus Kuizinas的正则表达式然后我做了这些重新定义:
(ns comment-forest
(:require [clojure.walk :refer [postwalk]]
[clojure.pprint :refer [pprint]])
(:import java.util.UUID))
(defn- key-seq [comment]
(->> comment
:level
(re-seq (re-pattern "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89aAbB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}"))
(map #(UUID/fromString %))
(interpose :children)))
;;This is just to print the trees with less unnecessary detail
(defn- prune [value]
(if
(or
(not (map? value))
(every? (partial contains? value) [:node :children])
(every? #(= UUID (type %)) (keys value)))
value
(select-keys value [:id :content])))
(pprint (map (partial postwalk prune) (list->forest querylist)))
获得输出
({:node
{:content "This is a top-level comment",
:id "ee9a2671-b47e-40ef-994f-a7b0fa81d717"},
:children
{#uuid "f28a159c-de66-4712-9cb8-e1841afeebf6"
{:node
{:content "Hey look at me",
:id "f28a159c-de66-4712-9cb8-e1841afeebf6"},
:children {}},
#uuid "d3fccc58-5e59-486d-b784-c54f0e4698b1"
{:node
{:content "This!", :id "d3fccc58-5e59-486d-b784-c54f0e4698b1"},
:children
{#uuid "e6387f7d-4f29-42c9-a386-7f799341f48f"
{:node
{:content "It sure is!",
:id "e6387f7d-4f29-42c9-a386-7f799341f48f"},
:children {}}}},
#uuid "3de27950-7340-49d1-a28e-54ad2e4ea0f1"
{:node
{:content "This is yet another testing comment",
:id "3de27950-7340-49d1-a28e-54ad2e4ea0f1"},
:children {}}}}
{:node
{:content "This is another top-level comment",
:id "fdc8a8b9-19c7-4fad-963d-2c2ca0bcbe8a"},
:children
{#uuid "b17bc5b8-9968-48ce-8ff3-83c8123cd327"
{:node
{:content "What a comment!",
:id "b17bc5b8-9968-48ce-8ff3-83c8123cd327"},
:children
{#uuid "1cee5390-e810-49b7-ad10-098bfbe03ab2"
{:node
{:content "No idea how this will turn out",
:id "1cee5390-e810-49b7-ad10-098bfbe03ab2"},
:children {}}}}}})
答案 2 :(得分:0)
原来@coredump有正确的想法。通过让顶级注释将其父ID作为主题,我可以使用clojure.zip/zipper轻松构建树。