如何将json文件读入Clojure defrecord(以后再搜索)

时间:2013-03-27 13:29:38

标签: json clojure

我在Clojure REPL中创建了一个defrecord:

user=> (defrecord Data [column1 column2 column3])
user.Data

如何通过读入.json文件自动将数据添加到此记录中? defrecord中的每一列都与json数据中的键完全对应。如果文件包含单个记录,则它看起来类似于:

[
  {
    "column1" : "value1"
    "column2" : "value2"
    "column3" : "value3"
  }
]

但文件中有数千条此类记录。

我可以像这样啜饮文件的内容:

(json/read-json (slurp "path/to/file.json")))

read-json函数的依赖项将从命令行lein repl中添加到我运行:dependencies [org.clojure/data.json "0.2.1"]的目录中的project.clj文件中。

我希望能够使用Clojure函数搜索记录的值,这样我传递给搜索函数的值就在单个记录的column1和column2值的值之间(即 nth-record.column1.value < = 查询 < = nth-record.column2.value )。一旦找到匹配的记录,我想在同一记录中返回另一列的值(nth-record.column3.value)。第1列和第2列的值将是唯一的,表示非重叠值范围。 column3的值不是唯一的。

这似乎是一项相当简单的任务,但我无法弄清楚如何使用Clojure文档或我在网上找到的示例。对我来说,只要我可以搜索它们并在同一记录中返回相关字段的值,如何将记录存储在Clojure内部并不重要。

2 个答案:

答案 0 :(得分:11)

使用data.json包:

(require '[clojure.data.json :as json])

将值读入内存:

(def all-records (json/read-str (slurp "path/to/file.json")
                :key-fn keyword))
;; ==> [ { :column1 "value1", :column2 "value2", :column3 "value3" }, ...]

查找匹配的记录:

(def query "some-value")
(def matching (filter #(and (< (:column1 %) query) (< query (:column2 %))) all-records))

获取第3列:

(map :column3 matching)

将所有内容收集起来(并使其更加灵活):

(defn find-matching [select-fn result-fn records]
   (map result-fn (filter select-fn records)))

(defn select-within [rec query]
  (and (< (:column1 rec) query) (< query (:column2 rec))))

(find-matching #(select-within % "some-value") :column3 all-records)

答案 1 :(得分:1)

  1. 应该使用柴郡来提高速度。
  2. 如果您的查询变得足够复杂,请考虑使用lucene,clojure有一个很好的包装。
  3. 我认为你认为记录在某种程度上比地图更适合这个,据我所知,你没有使用任何使记录特殊像多态的功能。可能有办法让柴郡吐出记录,但我不会打扰。