Clojure排序映射超过值

时间:2014-10-12 17:04:51

标签: sorting clojure

我正在尝试对值进行排序。

输入地图如下所示:

{:Blabla 1, :foo 1, :bla-bla 1, :Bla 2, :bla/bla 1, :bla 4, :blub 2, :hello 1, :Foo 2}

输出应如下所示:

{:bla 4 :Bla 2 :blub 2 :Foo 2 :Blabla 1 :bla-bla 1 :bla/bla 1 :foo 1 :hello 1}

我在这里的文档中使用了sorted-map-by: http://clojuredocs.org/clojure.core/sorted-map-by

(defn sort-keyword-list [texts]
  (let [results (word-counts texts)]
       ;results is now {:Blabla 1, :foo 1, :bla-bla 1, :Bla 2, :bla/bla 1, :bla 4, :blub 2, :hello 1, :Foo 2}
       (into (sorted-map-by (fn [key1 key2]
                                (compare [(get results key2) key2]
                                         [(get results key1) key1])))
             results))
  )

我发现只有关键字没有像“/”或“ - ”这样的特殊字符时,此解决方案才有效。这是一个已知的错误吗?

那么如何在不编写自己的缓慢排序算法的情况下快速按值排序地图呢?

2 个答案:

答案 0 :(得分:2)

这是一个基于@ user100464建议的解决方案,当值相同时,明确考虑了密钥的比较。

注意:我选择通过颠倒比较的参数顺序来减少排序:(compare (x k2)(x k1))和(compare k2 k1)

(defn sort-by-value-then-key [x]
  (into (sorted-map-by (fn [k1, k2]
                         (let [v_c (compare (x k2) (x k1))]
                           (if (= 0 v_c)
                             (compare k2 k1)))))
        x))

可以在(compare k2 k1)进行自定义,以实现更精细的密钥比较。

答案 1 :(得分:1)

在我的Clojure 1.6.0 REPL中,问题中的代码已按值排序:

user=> (into (sorted-map-by (fn [key1 key2]
                     (compare [(get x key2) key2]
                              [(get x key1) key1])))
    x)
{:bla 4, :blub 2, :Foo 2, :Bla 2, :bla/bla 1, :hello 1, :foo 1, :bla-bla 1, :Blabla 1}

如果要按键对具有相同值的条目进行排序,则需要对键进行字符串化。这就是原因:

user=> x
{:bla-bla 1, :Blabla 1, :bla/bla 1, :hello 1, :bla 4, :foo 1, :Bla 2, :Foo 2, :blub 2}
user=> (sort (keys x))
(:Bla :Blabla :Foo :bla :bla-bla :blub :foo :hello :bla/bla)
user=> (sort (map str (keys x)))
(":Bla" ":Blabla" ":Foo" ":bla" ":bla-bla" ":bla/bla" ":blub" ":foo" ":hello")