clojure:有效地确定字符串是否以集合中的任何前缀开头

我有一个前缀/值对的集合,并希望在此连接中找到与当前目标字符串开头的前缀相关联的任何值. (在多个前缀匹配的情况下,定义行为并不重要,因为我的用例的性质使得不应该发生).

一个天真(工作)的实施如下:

(defn prefix-match [target-str pairs]
  (some
    (fn [[k v]]
        (if (.startsWith target-str k)
            v
            false))
    pairs))

这样:

user=> (prefix-match "foobar" {"meh" :qux, "foo" :baz})
:baz

这是按预期的方式工作的,但是O(n)具有对序列的长度. (快速插入成对也是可取的,但不如快速查找那么重要).

首先要想到的是将有序的随机存取区分成一个排序的集合,但是我不知道Clojure中哪些数据结构最适合任务.建议?

最佳答案
一个特洛伊怎么样?

(defn build-trie [seed & kvs]
  (reduce
   (fn [trie [k v]]
     (assoc-in trie (concat k [:val]) v))
   seed
   (partition 2 kvs)))

(defn prefix-match [target trie]
  (when (seq target)
    (when-let [node (trie (first target))]
      (or (:val node)
          (recur (rest target) node)))))

用法:

user> (def trie (build-trie {} "foo" :baz "meh" :qux))
#'user/trie
user> trie
{\m {\e {\h {:val :qux}}}, \f {\o {\o {:val :baz}}}}
user> (prefix-match "foobar" trie)
:baz
user> (prefix-match "foo" trie)
:baz
user> (prefix-match "f" trie)
nil
user> (prefix-match "abcd" trie)
nil

转载注明原文:clojure:有效地确定字符串是否以集合中的任何前缀开头 - 代码日志