使用Clojure重新排序嵌套的有序映射

3

我有一个排序的映射表:

 (def my-map {1 {:foo "String_1" :ordnen 5 } 
              2 {:foo "String_2" :ordnen 4} 
              3 {:foo "String_3" :ordnen 3} 
              4 {:foo "String_4" :ordnen 1} })

我需要使用:ordnen关键字中保存的值以升序重新排序它。因此,最终排序后的映射将会是这样的:

  {4 {:foo "String_4" :ordnen 1}
   3 {:foo "String_3" :ordnen 3}
   2 {:foo "String_2" :ordnen 4} 
   1 {:foo "String_1" :ordnen 5 }}

我尝试过:

(into (sorted-map-by (fn [key1 key2] (compare (:ordnen key1) (:ordnen key2)))) my-map)

但我不明白如何获取并比较:ordnen的值。

2个回答

3

正确的方式

(into
 (sorted-map-by
  (fn [key1 key2]
    (compare
     [(get-in my-map [key1 :ordnen]) key1]
     [(get-in my-map [key2 :ordnen]) key2])))
 my-map)

如果您想按值排序。在您的情况下,值是地图,然后您需要按该地图中:ordnen键的值进行排序。(get-in my-map [key :ordnen])就是您想要排序的值,但是您需要确保比较器适用于唯一的值。因此,我们制作一个包含值和键的向量。

泰勒建议的上述方法对于非唯一值不起作用。我添加了另一个ordnen 4条目。

(def my-map {1 {:foo "String_1" :ordnen 5}
             2 {:foo "String_2" :ordnen 4}
             3 {:foo "String_2" :ordnen 4}
             4 {:foo "String_3" :ordnen 3}
             5 {:foo "String_4" :ordnen 1}})


(into (sorted-map-by
       (fn [key1 key2]
         (compare (:ordnen (get my-map key1))
                  (:ordnen (get my-map key2)))))
      my-map)

键为3的Map条目丢失。

{5 {:foo "String_4", :ordnen 1}, 4 {:foo "String_3", :ordnen 3}, 2 {:foo "String_2", :ordnen 4}, 1 {:foo "String_1", :ordnen 5}}

谢谢,问题是:为什么要写成 "[(get-in my-map [key1 :ordnen]) key1]" 而不是只写 "(get-in my-map [key1 :ordnen])" 呢? - aarkerio
2
由于 sorted-map-by 在内部的工作方式,如果任何传递给 compare 的键相等,则它们会被处理为在构建结果排序映射时重复使用 assoc。因此,这里存在数据丢失的可能性。例如,如果您执行 (-> {} (assoc :a 1) (assoc :a 2)),则 :a 上的值 1 将被覆盖为 2。我们确保 compare 的参数是唯一的,因此我们使用具有映射条目的键和 :ordnen 值的向量对(key1 和 key2 保证是唯一的,因此 [ordnen-val key1] 和 [ordnen-val key2] 也是唯一的)。 - Simon Polak

3

首先通过调用val从映射中获取值,然后在结果子映射上,只需通过关键字提取对应于:ordnen的值:

(sort-by (comp :ordnen val) my-map)

2
这是一个不错的解决方案,简短而简洁。只有一个小问题,op声明他想要一个排序的映射,但这给你提供了一个向量序列。 - Simon Polak
1
排序映射: (into {} (sort-by (comp :ordnen val) my-map)) - aarkerio
1
你还可以将一个比较器作为第二个参数传递给sort-by函数。假设你想要按降序对:ordnen进行排序,你可以这样写:(into (sorted-map) (sort-by (comp :ordnen val) > my-map)) - Simon Polak

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