Clojure: How to generate a 'trie'?

前端 未结 4 1141
死守一世寂寞
死守一世寂寞 2021-02-08 00:19

Given the following...

(def inTree
 \'((1 2)
   (1 2 3)
   (1 2 4 5 9)
   (1 2 4 10 15)
   (1 2 4 20 25)))

How would you transform it to this t

4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-08 00:23

    I'm sure there is a prettier way (there was! see Brian's answer it is better):

    (defn find-in-trie
      "Finds a sub trie that matches an item, eg:
      user=> (find-in-trie '(1 (2) (3 (2))) 3)
      (3 (2))"
      [tr item]
      (first (for [ll (rest tr) :when (= (first ll) item)] ll)))
    
    
    (defn add-to-trie
      "Returns a new trie, the result of adding se to tr, eg:
      user=> (add-to-trie nil '(1 2))
      (1 (2))"
      [tr se]
      (cond
        (empty? se) tr
        (empty? tr) (add-to-trie (list (first se)) (rest se))
        :else (if-let [st (find-in-trie tr (first se))]
                (cons (first tr)
                      (cons (add-to-trie st (rest se))
                            (filter (partial not= st) (rest tr))))
                (cons (first tr)
                      (cons (add-to-trie (list (first se)) (rest se))
                            (rest tr))))))
    
    (def in '((1 2)
              (1 2 3)
              (1 2 4 5 9)
              (1 2 4 10 15)
              (1 2 4 20 25)))
    
    (reduce add-to-trie '(nil) in)
    

    -> (nil (1 (2 (4 (20 (25)) (10 (15)) (5 (9))) (3))))

    Note that I've chosen to use nil as the root node and have not bothered keeping empty lists to signify no children. Actually doing it this way is not correct as it does not preserve substring identity.

提交回复
热议问题