Clojure 关于选择键功能的问题

Clojure 关于选择键功能的问题,clojure,Clojure,理想情况下,“选择关键点”(select keys)将返回一个包含关键点的贴图,其顺序与关键点顺序向量相同。但是我发现只有当你的钥匙少于10把时才会发生这种情况 (def params {:resource-total-calls-abandoned 1, :resource-idle-time 5, :date "2016-12-31", :resource-wrap-up-time 1, :agent-talk-time 1, :resource-work-offers 3, :aux-in

理想情况下,“选择关键点”(select keys)将返回一个包含关键点的贴图,其顺序与关键点顺序向量相同。但是我发现只有当你的钥匙少于10把时才会发生这种情况

(def params {:resource-total-calls-abandoned 1, :resource-idle-time 5, :date "2016-12-31", :resource-wrap-up-time 1, :agent-talk-time 1, :resource-work-offers 3, :aux-in-time 1, :user-id 2183, :resource-not-ready-time 3, :split 1, :aux-out-time 1, :resource-logged-in-time 1, :hold-time 115, :acd-calls 1})

(select-keys  params [:user-id
                                            :date
                                            :split
                                            :resource-logged-in-time
                                            :agent-talk-time
                                            :resource-wrap-up-time
                                            :hold-time
                                            :acd-calls
                                            :resource-total-calls-abandoned

                                            ])
以下是我的结果:

{:user-id 2183, :date "2016-12-31", :split 1, :resource-logged-in-time 1, :agent-talk-time 1, :resource-wrap-up-time 1, :hold-time 115, :acd-calls 1, :resource-total-calls-abandoned 1}
如果我有10多个关键点要从一个巨大的地图中选择,地图的顺序将不同于关键点的顺序

(select-keys  params [:user-id
                                            :date
                                            :split
                                            :resource-logged-in-time
                                            :agent-talk-time
                                            :resource-wrap-up-time
                                            :hold-time
                                            :acd-calls
                                            :resource-total-calls-abandoned
                                            :aux-in-time
                                            ])
结果会有所不同:

{:resource-total-calls-abandoned 1, :date "2016-12-31", :resource-wrap-up-time 1, :agent-talk-time 1, :aux-in-time 1, :user-id 2183, :split 1, :resource-logged-in-time 1, :hold-time 115, :acd-calls 1}

关于返回键按keyseq向量顺序排列的贴图的任何其他想法,无论您要选择多少键?

如果您想要具有顺序的关联结构,则有一个排序贴图可以保持其元素的顺序。一个现成的解决方案可能是首先选择您想要的关键点,然后将它们放入一个新的排序地图中

(def k [:user-id
        :date
        :split
        :resource-logged-in-time
        :agent-talk-time
        :resource-wrap-up-time
        :hold-time
        :acd-calls
        :resource-total-calls-abandoned
        :aux-in-time])

(->> (select-keys params k)
     (into (sorted-map-by #(< (.indexOf k %1) (.indexOf k %2)))))
比较器功能<。。。以上只是一个例子;如果以这种方式创建已排序的地图,则对其进行更新(例如assoc)肯定会出错。原因是向量k中的索引用于比较元素的顺序,但对于不在向量中的任何元素,它都是-1

一个更有效的解决方案是将地图上的数据简化为一个排序的数据结构


更新:根据@leetwinski的建议,将“应用”更改为“转化”,这样就无需在选择关键点后展平贴图。

如果您想要具有顺序的关联结构,则有一个排序贴图可以保持其元素的顺序。一个现成的解决方案可能是首先选择您想要的关键点,然后将它们放入一个新的排序地图中

(def k [:user-id
        :date
        :split
        :resource-logged-in-time
        :agent-talk-time
        :resource-wrap-up-time
        :hold-time
        :acd-calls
        :resource-total-calls-abandoned
        :aux-in-time])

(->> (select-keys params k)
     (into (sorted-map-by #(< (.indexOf k %1) (.indexOf k %2)))))
比较器功能<。。。以上只是一个例子;如果以这种方式创建已排序的地图,则对其进行更新(例如assoc)肯定会出错。原因是向量k中的索引用于比较元素的顺序,但对于不在向量中的任何元素,它都是-1

一个更有效的解决方案是将地图上的数据简化为一个排序的数据结构


更新:根据@leetwinski的建议,将“应用”更改为“转化”,这样就无需在选择键后展平地图。

地图未排序。它们看起来最多有8个条目,但这是一个实现细节,您永远不应该依赖它。看起来是这样的。谢谢,我没有时间给出一个正确的答案,但只是给出了一个简单的想法:您可以编写一个函数/宏,它接受keyseq并根据其顺序构建一个比较器,然后根据该比较器返回一个排序映射。是的,如果你看小于9 k/v对的映射,你会看到类型是PersistentArrayMap,对于更大的映射,它是PersistentHashMap-这是出现排序的原因,这是因为对于大型映射,散列会更快,对于非常小的映射,基于数组的实现更为有效。@Josh顺便说一句,我的库中已经存在这种映射。映射没有顺序。它们看起来最多有8个条目,但这是一个实现细节,您永远不应该依赖它。看起来是这样的。谢谢,我没有时间给出一个正确的答案,但只是给出了一个简单的想法:您可以编写一个函数/宏,它接受keyseq并根据其顺序构建一个比较器,然后根据该比较器返回一个排序映射。是的,如果你看小于9 k/v对的映射,你会看到类型是PersistentArrayMap,对于更大的映射,它是PersistentHashMap-这是出现排序的原因,这是因为对于大型映射,散列会更快,对于非常小的地图,基于数组的实现更为有效。@Josh顺便说一句,我的图库中已经有了这个概念。有趣的想法,我喜欢它!可以这样简化:->>按<.indexOf k%1.indexOf k%2将键参数k选择到已排序的映射中。使用into而不是apply将消除展平选定关键点的需要map@leetwinski谢谢我相应地更新了答案。太棒了。这是一个伟大的想法,我喜欢!可以这样简化:->>按<.indexOf k%1.indexOf k%2将键参数k选择到已排序的映射中。使用into而不是apply将消除展平选定关键点的需要map@leetwinski谢谢我相应地更新了答案。太棒了。好主意