私はきれいな方法は、(あった方が良いですブライアンの答えを参照してください!)があると確信している:
(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)
- >(ゼロ(1(2(4(20(25))(10私はルートノードとしてnilを使用することを選択したと子を意味しないように空のリストを維持困っていません(15))(5(9)))(3))))
注意。この方法で実際に行うのは、部分文字列の同一性が保持されないため正しくありません。
ブライアンのバージョンは、いつも同じ数のキーを使用していればいいと思いますか? – Johnny
'prefix-matches'の定義には関数' map-filter'が使われていますが、そのような関数は標準ライブラリにはありません。私はリバースエンジニアリングを試みましたが、それは明らかではありません。その定義を投稿できますか? –
'map-filter'はコアlibにある' keep'に似ています。 – NielsK