select-keys函数是否保留其键序列的顺序?

3

看这个例子:
(into [] (select-keys {:a 1 :b 2 :c 3} [:c :b])) => [[:c 3] [:b 2]]
请问返回的结果是否保证了 select-key 函数第二个参数中声明的顺序?

3个回答

8

select-keys 返回的是一个无序的 map,所以你不能依赖它。小型的 map 被表示为数组,这维护了顺序,但是当大小增加时,这种顺序会被打破。

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

1
这不是一个可靠的函数来保留顺序,以及keysvals不保留您定义映射的顺序。最可靠的方法是使用loop/recur,如果您想输出kv有序向量(或reduce也可以)。如果您只需要有序值,可以使用juxt。我想补充说,从实用角度来看,hashmap不适合表示有序数据。

没错,关联的无序数据结构并不旨在收集有序数据,但Clojure仍然有sorted-mapsorted-map-by,这就是我对这个问题产生兴趣的原因。 - foki

1
如果排序相对简单,您可以使用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]]

即使排序不简单,你仍然可以编写自定义比较器。这充满了陷阱,但有一篇非常好的指南。虽然它不是你最初想要的,但它与此相关。

1
请注意,(sorted-map-by compare) 等同于 (sorted-map) - Sam Estep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接