简体   繁体   中英

Does select-keys preserve order from its keyseq?

Looking at the example:
(into [] (select-keys {:a 1 :b 2 :c 3} [:c :b])) => [[:c 3] [:b 2]]
Is it guaranteed that returned result will preserve order declared in second parameter of select-key ?

select-keys returns a map which are unorderd, so you can't rely on it. Small maps are represented as arrays which do maintain order but this is broken as the size increases eg

(def m {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9 :j 10 :k 11 :l 12 :m 13})
(into [] (select-keys m [:a :b :c :d :e :f :g :h :i :j :k]))
=> [[:e 5] [:k 11] [:g 7] [:c 3] [:j 10] [:h 8] [:b 2] [:d 4] [:f 6] [:i 9] [:a 1]]

It's not a reliable function to preserve orders, as well as keys and vals which do not preserve the order of how you defined the map. The most reliable way is to use a loop / recur if you want to output an ordered vector of kv (or a reduce as well). If you want ordered values only, you can use juxt .

I would add that pragmatically hashmaps are not meant to represent ordered data.

If the ordering is a fairly simple one, you can easily sort the map by using sorted-map-by :

(def m (select-keys {:a 1 :b 2 :c 3 :d 4} [:d :b]))
=> {:d 4, :b 2}

(def sm (sorted-map-by compare)) 
(into sm m)
=> {:b 2, :d 4}

(assoc *1 :c 1234)
=> {:b 2, :c 1234, :d 4}  ; maintains sort when additional kvs are assoc'd

(into [] *1)
=> [[:b 2] [:c 1234] [:d 4]]

Even if the ordering is not simple, you can write a custom comparator. This is rife with pitfalls, but there is a guide that is very good. It's not what you were originally after, but it's relevant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM