Omr*_*ein 6 macros associative-array casting clojure hashmap
作为前言,我在Windows 7(64位)上运行Java版本6(更新33),使用clooj作为我的IDE.我没有尝试在任何其他系统中重现我的问题.我对Clojure很有经验,但对Java一点也不熟悉.
我试图解决的问题的全部内容很难描述,但它归结为:我想说我想制作一个带有一个参数的宏,一个关联映射,并返回一个元素的向量地图与他们的订单保存.
=>(defmacro vectorize-a-map
[associative-map]
(vec associative-map))
=>#'ns/vectorize-a-map
=>(vectorize-a-map {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8}
=>[[:a 1] [:b 2] [:c 3] [:d 4] [:e 5] [:f 6] [:g 7] [:h 8]]
Run Code Online (Sandbox Code Playgroud)
这是有效的,但添加另一个元素到地图和订单搞砸...
=>(vectorize-a-map {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9}
=>[[:a 1] [:c 3] [:b 2] [:f 6] [:g 7] [:d 4] [:e 5] [:i 9] [:h 8]]
Run Code Online (Sandbox Code Playgroud)
我相信我已经发现了为什么会这样.似乎任何具有8个或更少元素的东西都被实例化为PersistentArrayMap,这正是我想要的,因为据我所知,这个类保留了顺序.但是,具有9个或更多元素的任何内容都将实例化为PersistentHashMap,而不会保留顺序.
=>(type {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8}
=>clojure.lang.PersistentArrayMap
=>(type {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9}
=>clojure.lang.PersistentHashMap
Run Code Online (Sandbox Code Playgroud)
我希望我的宏能够获取任何大小的关联映射,所以这是一个问题.我曾尝试类型提示,解构结合,为列表理解,和所享有的拼接,都没有成功.要绘制出来,以下任何一个都不会起作用:
(defmacro vectorize-a-map
[^clojure.lang.PersistentArrayMap associative-map]
(vec associative-map))
(defmacro vectorize-a-map
[[& associative-map]]
(vec associative-map))
(defmacro vectorize-a-map
[associative-map]
(vec
(for [x associative-map]
x)))
(defmacro vectorize-a-map
[associative-map]
`(vector ~@associative-map))
Run Code Online (Sandbox Code Playgroud)
由于我提出这个玩具问题,我意识到我可以简单地编写我的宏,并完全避免这个问题:
=>(defmacro vectorize-kvs
[& elements]
(vec (map vec (partition 2 elements))))
=>#'ns/vectorize-kvs
=>(vectorize-kvs :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9)
=>[[:a 1] [:b 2] [:c 3] [:d 4] [:e 5] [:f 6] [:g 7] [:h 8] [:i 9]]
Run Code Online (Sandbox Code Playgroud)
但是,对于我试图解决的实际问题(我还没有进入),重要的是(虽然不是100%必要)宏可以采用关联映射.看起来我正在寻找如何在任何事情发生之前将参数转换为PersistentArrayMap.我可能还有其他一些解决方案,我根本就没有考虑或意识到这一点.
我已经研究了我所知道的最好的,但还没有发现任何有用的东西.有没有人有任何想法/建议?
你可以使用array-map制作你的地图
user> (map vec (array-map 1 2 3 4 5 6))
([1 2] [3 4] [5 6])
Run Code Online (Sandbox Code Playgroud)
或者使用更大的地图
user> (map vec (apply array-map (range 50)))
([0 1] [2 3] [4 5] [6 7] [8 9] [10 11] [12 13] [14 15] [16 17] [18 19] [20 21] [22 23] [24 25] [26 27] [28 29] [30 31] [32 33] [34 35] [36 37] [38 39] [40 41] [42 43] [44 45] [46 47] [48 49])
Run Code Online (Sandbox Code Playgroud)
作为奖励你可以避免使用宏,这是有用的,因为宏不是一流的,不能很好地组成*
Note that an array map will only maintain sort order when un-'modified'. Subsequent assoc-ing will eventually cause it to 'become' a hash-map.
如果您发现自己取决于地图中按键的顺序,您可能需要考虑是否sorted-map能满足您的需求.它会比一个更好地扩展array-map.在上面的例子中,输出是相同的:
(map vec (apply sorted-map (range 5000)))
[0 1] [2 3] ... [4998 4999]
Run Code Online (Sandbox Code Playgroud)
*这是我的意见
的时间comparason sorted-map与array-map
user> (time (dorun (map vec (apply sorted-map (range 500000)))))
"Elapsed time: 391.520491 msecs"
nil
user> (time (dorun (map vec (apply array-map (range 500000)))))
"Elapsed time: 674517.821669 msecs"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
366 次 |
| 最近记录: |