保存+读取已排序的地图到Clojure中的文件

时间:2013-06-27 15:56:25

标签: clojure

我正在通过spit将嵌套的数据地图保存到磁盘。我想要对我的地图中的一些地图进行排序,并在我slurp地图回到我的程序时保持排序。排序映射没有唯一的文字表示,因此当我spit映射到磁盘上时,排序映射和未排序映射表示相同,并且#(read-string (slurp %))数据使得每张地图都是通常未分类的。这是一个说明问题的玩具示例:

(def sorted-thing (sorted-map :c 3 :e 5 :a 1))
;= #'user/sorted-thing
(spit "disk" sorted-thing)
;= nil
(def read-thing (read-string (slurp "disk")))
;= #'user/read-thing

(assoc sorted-thing :b 2)
;= {:a 1, :b 2, :c 3, :e 5}
(assoc read-thing :b 2)
;= {:b 2, :a 1, :c 3, :e 5}

是否有某种方法可以首先按照排序方式读取地图,而不是在阅读后将它们转换为有序地图?或者这是否是我应该使用某种真实数据库的标志?

2 个答案:

答案 0 :(得分:4)

我认为它不一定表明您应该使用数据库,但我认为这表明您不应该使用spit。将已排序的映射写入磁盘时,请勿使用映射文字语法。如果你用以下格式写出来,read-string将起作用:

(def sorted-thing (eval (read-string "(sorted-map :c 3 :e 5 :a 1)")))
(assoc sorted-thing :b 2)
;= {:a 1, :b 2, :c 3, :e 5}

答案 1 :(得分:4)

*print-dup*动态可重新绑定的Var旨在支持此用例:

(binding [*print-dup* true]
  (prn (sorted-map :foo 1)))
; #=(clojure.lang.PersistentTreeMap/create {:foo 1})

注释掉的行是打印出来的。

当应用于Clojure数据结构时,它也会影响str,因此也会spit,所以如果你这样做

 (binding [*print-dup* true]
   (spit "foo.txt" (sorted-map :foo 1)))

写入foo.txt的地图表示将是上面显示的地图。

不可否认,我不是百分之百确定这是否记录在某处;如果您对此感到不安,则可以始终spit使用pr-str*print-dup*绑定true的结果:

(binding [*print-dup* true]
  (pr-str (sorted-map :foo 1)))
;= "#=(clojure.lang.PersistentTreeMap/create {:foo 1})"

(这次最后一行是返回的值而不是打印输出。)

显然,您必须*read-eval*绑定到true才能读回这些文字。这很好,但它正是它的服务目的(从可信来源读取代码)。