ClojureScript zipmap 欺骗了我还是什么?

ClojureScript zipmap tricks me or what?

我使用 Clojurescript 开发网络浏览器游戏。 (实际上是我的一个朋友教我的,我们几周前才开始)。

我想生成一个地图,其中键是向量,值是数字。例如:{[0 0] 0, [0 1] 1, [0 2] 2, ...}.

我使用了这个公式:

 (defn oxo [x y]
   (zipmap (map vec (combi/cartesian-product (range 0 x) (range 0 y))) (range (* x y))))

(其中 combi/ 指的是 clojure.math.combinatorics)。

生成地图时,键值对是可以的,但是它们的顺序是随机的,比如:

{[0 1] 1, [6 8] 68, [6 9] 69, [5 7] 57, ...}

使用 zipmap 后出了什么问题,我该如何解决?

Clojure 映射不保证有 ordered/sorted 个键。如果要确保对键进行排序,请使用 sorted-map:

(into (sorted-map) (oxo 10 10))
=>
{[0 0] 0,
 [0 1] 1,
 [0 2] 2,
 [0 3] 3,
 [0 4] 4,
 [0 5] 5,
...

如果您的地图的键少于 9 个,则 插入 顺序将被保留,因为底层数据结构因键数而异:

  1. clojure.lang.PersistentArrayMap <9 个键
  2. clojure.lang.PersistentHashMap否则

array-map 生成 clojure.lang.PersistentArrayMapsorted-map 生成 clojure.lang.PersistentTreeMap。请注意,assoc访问数组映射可能会生成 散列 映射,但 assoc访问排序映射仍会生成排序映射。

zipmap 生成一个散列映射,其中键的顺序无法保证。 如果你想要有序的密钥,你可以使用 sorted-maparray-map.

据我所知,您不应该依赖 Map/Hash/Dictionary 来订购任何语言。

如果顺序很重要,但您不需要 O(1) 的地图查找性能,向量对向量是您的不错选择。

(defn oxo [x y]
  (mapv vector (map vec (combi/cartesian-product (range 0 x) (range 0 y))) (range (* x y))))

你会得到这样的东西。

=> (oxo 10 10)
[[[0 0] 0] [[0 1] 1] [[0 2] 2] [[0 3] 3] [[0 4] 4] [[0 5] 5] ...]