如何在Clojure中序列化和反序列化有序地图?
例如:
(sorted-map :a 1 :b 2 :c 3 :d 4 :e 5)
{:a 1, :b 2, :c 3, :d 4, :e 5}
我注意到了什么:
其他资源:
答案 0 :(得分:1)
同样的问题有两个可用的答案:Saving+reading sorted maps to a file in Clojure。
第三个答案是设置自定义阅读器文字。您可以将排序后的地图打印为
;; non-namespaced tags are meant to be reserved
#my.ns/sorted-map {:foo 1 :bar 2}
然后在读取时使用适当的数据函数(从哈希映射转换为有序映射)。您可以选择是否要处理自定义比较器(这是一般无法解决的问题,但当然可以选择处理特殊情况)。
clojure.edn/read
接受可选的opts
地图,该地图可能包含:reader
密钥;然后,该键的值被视为一个映射,指定哪些数据读取器用于哪些标记。有关详细信息,请参阅(doc clojure.edn/read)
。
对于打印,您可以为print-method
安装自定义方法,或使用自定义函数打印已排序的地图。我可能会选择后一种解决方案 - 为内置类型实现内置协议/多方法通常不是一个好主意,所以即使在特定情况下看起来合理,它也需要额外的照顾等等。更简单地使用自己的功能。
更新
如大卫答案评论中所承诺的那样,演示如何彻底重用IPersistentMap
的{{1}} impl:
print-method
有了这个:
(def ^:private ipm-print-method
(get (methods print-method) clojure.lang.IPersistentMap))
(defmethod print-method clojure.lang.PersistentTreeMap
[o ^java.io.Writer w]
(.write w "#sorted/map ")
(ipm-print-method o w))
答案 1 :(得分:0)
在data_readers.clj
:
{sorted/map my-app.core/create-sorted-map}
注意:我希望这可行,但它没有(不确定原因):
{sorted/map clojure.lang.PersistentTreeMap/create}
现在,在my-app.core
:
(defn create-sorted-map
[x]
(clojure.lang.PersistentTreeMap/create x))
(defmethod print-method clojure.lang.PersistentTreeMap
[o ^java.io.Writer w]
(.write w "#sorted/map ")
(print-method (into {} o) w))
作为替代方案 - 较低级别,您可以使用:
(defn create-sorted-map [x] (into (sorted-map) x))
测试:
(deftest reader-literal-test
(testing "#sorted/map"
(is (= (sorted-map :v 4 :w 5 :x 6 :y 7 :z 8)
#sorted/map {:v 4 :w 5 :x 6 :y 7 :z 8}))))
(deftest str-test
(testing "str"
(is (= "#sorted/map {:v 4, :w 5, :x 6, :y 7, :z 8}"
(str (sorted-map :v 4 :w 5 :x 6 :y 7 :z 8))))))
这很大程度上取决于我在上面找到的资源。
注意:我很惊讶print-method
在上面工作。在我看来,(into {} o)
会失去排序,从而打乱了打印,但它在我的测试中起作用。我不知道为什么。