複雑なタイトルでごめんなさい、私はそれを意識させるために最善を尽くしました。さて、あなたがより良いアイデアを持っているなら、それを変えてください!
混乱しないように、これはEmacs Lisploop
であり、CommonLispではありません。
(defun hxswfml-build-trie (alist)
"Builds a trie (a list, containing number of hash-maps, each hash-map
uses single character for a key, except for `t' symbol, which, if present
as a key is the key for the value one has to substitute with."
(loop for (key . value) in alist
with trie = (make-hash-table)
do (loop for c across key
with branch =
(or (gethash c trie)
(puthash c (make-hash-table) trie))
with first-time = t
do (if first-time (setq first-time nil)
(setq branch
(or (gethash c branch)
(puthash c (make-hash-table) branch))))
finally (puthash t value branch))
finally (return trie)))
これにより、リストがハッシュテーブルで構成されたツリーに変換されます。各テーブルには、後で検索して置換する文字列の文字であるキーが含まれています。これは、テキストの大きな本文でおそらく同様のプレフィックスを持つ複数のキーの検索を最適化し、それぞれを対応するキーに置き換えるために必要です。
branch
問題は、内側のループで初期化しtrie
、その後のすべての反復で、新しいハッシュテーブル(既知のプレフィックスの一部ではない文字用に作成された)またはハッシュテーブルのいずれかに設定したいということです。これは、プレフィックスからの文字に対してすでに作成されています。
理想的には、次のようになります。
for branch = (or (and branch (gethash c branch)) (puthash c (make-hash-table) trie))
;; ^-----------------^------- cannot reference it here
first-time
そしてそれが私が避けられた愚かな旗を持っている理由です。どういうわけかinitially
フォームを使用できますか、またはこのフラグとそれによる余分なものを回避するために他の方法で関数を再構築できますif
か?この関数が高速であることはそれほど重要ではありませんが(検索は高速である必要がありますが、ツリーの構築は高速である必要はありません)、見た目は醜いです:)