如何在 Clojure 映射中排序键?理想情况下,根据键向量对它们进行排序

问题描述 投票:0回答:3

我找到了关于如何按值排序地图的不同解决方案,但没有找到关于如何让键以特定顺序出现的解决方案。

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

例如,给定一张地图:

(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
对地图矢量执行此操作,但我无法应用这种类型。

有什么想法吗?

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

clojure
3个回答
2
投票

我想这会让你到达那里

(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


1
投票

您需要以下内容:

(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}

使用我最喜欢的模板项目.

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

另请参阅此文档列表,尤其是 Clojure CheatSheet。

更新

如果您只需要将一些地图导出为 CSV,您可能会发现 tupelo.csv 库很有用。单元测试显示代码的运行


0
投票

还请考虑使用以下方法获取地图,其中的键按照向量中的描述进行排序:

(defn get-map-sorted-by-order
  [some-map keys-order]
  (into (sorted-map-by (fn [first-key second-key]
                         (< (.indexOf keys-order first-key)
                            (.indexOf keys-order second-key))))
        some-map))

它使用Java的

.indexOf
。不过,我觉得很方便。

(get-map-sorted-by-order
 {:hello "Hello", :world "World", :comma-space ", ", :exclamation "!"}
 [:hello :comma-space :world :exclamation])

导致以下结果:

{:hello "Hello", :comma-space ", ", :world "World", :exclamation "!"}
© www.soinside.com 2019 - 2024. All rights reserved.