我正在寻找Clojure数据结构,它像关系表一样工作(就像在关系数据库中一样)。
地图(甚至是biderectional)id - > (val1,val2,val3,...)不能完成这项工作。例如,如果我想要找到val2 =&#34的所有行;那么"它需要O(n)。
但我想在O(log n)的列中执行搜索!
答案 0 :(得分:1)
使用没有索引的列谓词在数据库中搜索行是O(n),因为如果它与谓词匹配,则必须检查每一行。如果谓词使用的列有索引,则可以使用索引查找特定值的所有行,方法是将该值作为索引中的键来查找所有匹配的行。然后通常是log(n)操作(它取决于索引的内部实现,例如对于B-tree,它是log(n))。
我不知道Clojure数据结构的开箱即用的实现具有通常具有单一用途的特性(例如,map是用于通过单个键查找的关联数据结构,而不是多个键,如具有多个索引的DB)。您宁愿需要一个提供某种内存数据库的库,例如(如他的注释中的Thumbnail所述)DataScript,甚至需要具有JDBC接口的内存SQL DB(例如H2SQL ,HSQLDB或DerbyDB使用其内存商店。)
我不确定您的具体要求,但您也可以使用Clojure的基本API自行实现某些功能。例如,您可以使用Clojure集作为"表"并使用clojure.set
中的一些函数增强它:
你的桌子:
(def my-table #{{:id 1 :name "John" :age 30 :gender :male}
{:id 2 :name "Jane" :age 25 :gender :female}
{:id 3 :name "Joe" :age 40 :gender :male}})
并指定您的指数:
(def by-id (clojure.set/index my-table [:id]))
(def by-age (clojure.set/index my-table [:age]))
(def by-gender (clojure.set/index my-table [:gender]))
然后在查询/过滤表时使用索引:
(clojure.set/intersection
(by-age {:age 30})
(by-gender {:gender :male}))
;; => #{{:id 1, :name "John", :age 30, :gender :male}}