Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Clojure中重新排序地图?_Clojure - Fatal编程技术网

如何在Clojure中重新排序地图?

如何在Clojure中重新排序地图?,clojure,Clojure,我有一张这样的有序地图: {: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] ) 我可能会将排序向量转换为哈希映射,以快速查找排序索引,结果如下: { :c 0 :a 1 } 有几种方法可以

我有一张这样的有序地图:

{: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] )

我可能会将排序向量转换为哈希映射,以快速查找排序索引,结果如下:

{ :c 0  :a 1 }
有几种方法可以从一个seq/向量中自动执行该操作(例如,使用
范围
映射
,然后使用
关联
减少为{})。将结果(或上面的文字映射)绑定到本地(使用
let
),我们称之为
顺序映射

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

(select-keys m order)
并使用比较器函数(如下所示)将过滤后的表达式的结果放回新的排序映射(使用
排序映射依据
):

(fn [a b] (compare (order-map a) (order-map b)))
请注意,如果您实际上不需要它作为一个映射,而序列也可以,那么您可以使用
排序依据
和使用相同顺序映射的键函数

把这些放在一起,你会得到:

(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))))
以及:


下面是一个简单的方法:

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

更新:如评论中所述,此解决方案仅适用于小地图(请参阅),最终依赖于底层数据结构的隐藏实现细节。公认的答案是正确的。

我试过了,但没有定义“顺序图”。您试用了哪个版本的clojure?如果不清楚,很抱歉-您需要将生成的排序映射绑定到类似于
排序映射
的东西。更新了一点解释。您需要执行类似于
(让[ordermap{:c0:a1}]
然后在let-block中执行其余操作。啊,谢谢。当有超过50个条目时,这个版本可以工作吗?是的,据我所知,这个版本在所有情况下都是正确的。据我所知,映射成为哈希表的截止点目前是32个条目,因此就是这个例子。事实上,
(连词{}(选择键…)
似乎根本不起作用的是一个实现细节,在Clojure的未来版本中可能会发生变化。据我所知,映射基本上是列表,使用线性搜索直到32个条目的截止点,这就是它们保持排序的原因。除此之外,它们被实现为哈希树。@pmjordan截止点实际上是每年10个条目现在是这样。由于整数作为映射键散列的方式,它看起来可能是32,但如果使用小整数以外的其他值,很明显变化发生在10。不幸的是,一旦映射变得足够大,可以转换为适当的散列表,这将失败。尝试一个包含50个条目的示例,您将看到我所说的内容一个具体的例子:
(asort(apply sorted map(interleave(range 0 50)(range 0 50)))(range 32 0-1))
应该生成
{32 31 31…1}
,但在我的机器上根本不是这样。
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}