2014-10-12 3 views
3

Я пытаюсь сортировать карту по значениям.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} 

Я отсортирован карта-мимо, как в документации здесь: 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)) 
) 

Ну, я узнал, что это решение работает только в том случае, если keywo У rds нет специальных символов, таких как «/» или «-» внутри. Это известная ошибка?

Итак, как я могу сортировать карту по значениям быстро, не создавая собственный алгоритм медленного сортировки?

ответ

1

В моем Clojure 1.6.0 РЕПЛ код в вопросе уже сортирует по значению:

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} 

Если вы хотите записи с одинаковым значением для сортировки по ключу, вам необходима stringify ключей. Вот почему:

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") 
+0

Я хочу сортировать значения в первом порядке, чем, возможно, над ключами. – Kingalione

+0

Я не уверен, что понимаю вашу цель. Ваш код уже создает карту, сортирующую по значению. Если вы не хотите сортировать ключи, у вас уже есть рабочий код. Если вы хотите отсортировать ключи для устранения неоднозначности записей с одинаковым значением, вы, вероятно, захотите сначала сжать ключи. – user100464

+0

В моем REPL он не сортирует карту над значениями. Выходной и входной то же самое – Kingalione

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) реализовать более сложный ключ сравнения.

Смежные вопросы