【问题标题】:Data structure methods on clojureclojure 上的数据结构方法
【发布时间】:2016-08-25 20:08:30
【问题描述】:

如何转换此列表:

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

【问题讨论】:

    标签: list clojure tree


    【解决方案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(B D) 是相等的)

    然后我会使用递归函数构造树:

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

    【讨论】:

    • to-tree 的尾调用优化版本会是什么样子?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多