关于clojure

时间:2016-08-25 20:08:31

标签: list clojure tree

如何转换此列表:

'((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的子女。

1 个答案:

答案 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))))))))