如何在 Clojure 地图中订购钥匙?理想情况下,根据键向量对它们进行排序

How to order keys in Clojure map? Ideally sort them against a vector of keys

我找到了关于如何按值对地图进行排序的不同解决方案,但是 none 关于如何让键以特定顺序出现的问题。

我们知道键是自动排序的,不会以它们插入的方式出现,但我们可以在之后以某种方式强制它吗?

例如,给定一张地图: (def my-map {:one 1 :two 2 :three 3 :four 4 :five 5}), 我想更改它们的显示顺序。

所需的键在向量中 (def sorted-keys-here [:four :three :five :two :one])

这样,我希望地图在 sort-fn 应用后显示为:

=> {:four 4 :three 3 :five 5 :two 2 :one 1}

密钥始终是固定的,我会使用 map 对地图矢量执行此操作,但我无法应用这种类型。

有什么想法吗?

(编辑:问题不在于顺序没有维护。实际问题是如何使映射中的键符合指定顺序。映射将来自其他地方并正在经历转换在中间,所以无论如何都不可能从一开始就以正确的顺序得到它。

我想这会让你到达那里

(def my-map {:one 1 :two 2 :three 3 :four 4 :five 5})
(map my-map [:four :three :five :two :one])  ;

您可以即时放置您的通用键向量

(def vector-seq [:two :one])
(map my-map vector-seq)  ; this will return list
(mapv my-map vector-seq)  ; this will return vector

或者你可以做的是“加权”输入向量

(let [my-map {:one 1 :two 2 :three 3 :four 4 :five 5}
      vector-seq [:five :three :two :four :one]
      weight (apply hash-map (interleave vector-seq (range (count vector-seq))))]
  (into 
        (sorted-map-by 
            (fn [key1 key2]
                (> (get weight key2)
                  (get weight key1))))
        my-map ))

这将产生 sorted-map 序列为 vector-seq

您需要如下内容:

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(dotest 
  (let [keys-ordered  [:one :two :three :four :five :six]
        keys->idx     (zipmap keys-ordered (range))
        order-fn      (fn [x y] (< (keys->idx x) (keys->idx y))) ; a comparitor
        m             {:one 1 
                       :two 2
                       :three 3
                       :four 4
                       :five 5 
                       :six 6}

        m-sorted-norm (into (sorted-map) m)
        m-sorted-custom (into (sorted-map-by order-fn) m) ]

    (spyx-pretty m-sorted-norm)
    (spyx-pretty m-sorted-custom)
  ))

这将产生:

m-sorted-norm =>
{:five 5, :four 4, :one 1, :six 6, :three 3, :two 2}

m-sorted-custom =>
{:one 1, :two 2, :three 3, :four 4, :five 5, :six 6}

使用 my favorite template project.

但是,请记住,经过排序的地图只会影响它们在终端上的打印方式。对于所有其他用途,使用排序映射没有任何好处(维护它们可能会很痛苦)。

另请参阅 this list of documentation,尤其是 Clojure CheatSheet。

更新

如果您只需要将一些地图导出为 CSV,您可能会发现 tupelo.csv library useful. The unit tests show the code in action