如何在Clojure中重新排序一个map?

7

我有一个有序映射,如下所示:

{:a 1 :b 2 :c 3}

假设给出一系列排序列表:

[:c :a]

我希望找到最简单的方法来获取:

{c: 3 :a 1}

: 有人知道如何做到这一点吗?

更新:

(defn asort [amap order]  (conj {} (select-keys amap order)))

(asort {:a 1 :b 2 :c 3} [:c :a] )
2个回答

11

我可能会将顺序向量转换为哈希映射以快速查找顺序索引,从而得到以下结果:

{ :c 0  :a 1 }

有几种方法可以从一个序列/向量(比如使用maprange,然后使用assoc将结果缩减为一个{})自动执行此操作。将该操作的结果(或上面的字面值映射)绑定到本地变量中(使用let),我们称其为order-map

然后过滤原始映射(m)的条目,只包括在排序中包含的条目:

(select-keys m order)

然后将过滤表达式的结果放回一个新的排序映射中(使用sorted-map-by),并使用类似以下的比较器函数:

(fn [a b] (compare (order-map a) (order-map b)))

请注意,如果你实际上不需要一个 map,而只是需要一个序列,你可以使用 sort-by 函数并使用与原来的有序 map 相同的键函数。

将这些组合在一起,你会得到:

(defn asort [m order]
  (let [order-map (apply hash-map (interleave order (range)))]
    (conj
      (sorted-map-by #(compare (order-map %1) (order-map %2))) ; empty map with the desired ordering
      (select-keys m order))))

并且:

=> (asort (apply sorted-map (interleave (range 0 50) (range 0 50))) (range 32 0 -1))
{32 32, 31 31, 30 30, 29 29, 28 28, 27 27, 26 26, 25 25, 24 24, 23 23, 22 22, 21 21, 20 20, 19 19, 18 18, 17 17, 16 16, 15 15, 14 14, 13 13, 12 12, 11 11, 10 10, 9 9, 8 8, 7 7, 6 6, 5 5, 4 4, 3 3, 2 2, 1 1}

我尝试过了,但是出现了“order-map”未定义的错误。你是在哪个版本的Clojure上尝试的? - yazzapps.com
抱歉如果之前没有表述清楚 - 你需要将生成的排序映射绑定到类似于 order-map 的东西上。稍微更新了一下解释。你需要这样做: (let [order-map { :c 0 :a 1 }] 然后在该 let 块内完成其余操作。 - pmdj
啊,谢谢。这个版本在超过50个条目时能正常工作吗? - yazzapps.com
1
@pmjordan 实际上,目前截止是10个条目。由于整数哈希作为映射键的方式,它可能看起来像32,但如果您使用的不是小整数,则很明显更改发生在10个条目处。 - amalloy
现在是否有clojure.core中的等效物,有人知道吗? - roboli
显示剩余2条评论

2
这里有一个简单的方法:

以下是实现的步骤:

(defn asort [amap order]
 (conj {} (select-keys amap order)))

导致结果为:
clojure.core> (asort {:a 1 :b 2 :c 3} [:c :a])
{:c 3, :a 1}
clojure.core> (asort {:a 1 :b 2 :c 3} [:a :c])
{:a 1, :c 3}

更新:如评论中所述,此解决方案仅适用于小型地图(请参见HASHTABLE_TRESHOLD),最终依赖于基础数据结构的隐藏实现细节。接受的答案是正确的。


9
很不幸,一旦地图足够大可以转换成一个适当的哈希表,这种方法就会失败。尝试使用50个条目的示例,你会明白我在说什么。 - pmdj
3
具体例子:(asort (apply sorted-map (interleave (range 0 50) (range 0 50))) (range 32 0 -1)) 应该生成 { 32 32 31 31 ... 1 1 },但在我的电脑上却不是这样。 - pmdj

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