如何转换此列表:
'((A B) (A C) (C D) (B D) (D E) (D F))
像
这样的东西'(A (B (nil)) (C (D ((F (nil)) (E (nil))))))
或者最能代表树的列表:
A
/ \
B C
|
D
/ \
E F
请注意,由于C是第一个声称D作为其子女的人,因此(B D)并未将D添加为B的子女。
答案 0 :(得分:1)
首先,我会清理数据,删除所有不必要的对(在你的情况下'(B D)),并构建邻接映射:
user> (def data '((A B) (A C) (C D) (B D) (D E) (D F)))
#'user/data
user> (def nodes-map (group-by first
(apply sorted-set-by
#(compare (second %1) (second %2))
data)))
#'user/nodes-map
user> nodes-map
{A [(A B) (A C)], C [(C D)], D [(D E) (D F)]}
我使用sorted-set
删除垃圾,使用比较器将项目视为相等的事实,并仅保留第一个(在这种情况下,它认为(C D) and
(BD)是等于)
然后我将使用递归函数构建树:
user> (defn to-tree [start nodes]
(list start
(if-let [connections (seq (nodes start))]
(map #(to-tree (second %) nodes) connections)
'(nil))))
#'user/to-tree
user> (to-tree 'A nodes-map)
(A ((B (nil)) (C ((D ((E (nil)) (F (nil))))))))