Как изменить порядок карты в Clojure? - PullRequest
6 голосов
/ 25 марта 2011

У меня есть заказанная карта примерно так:

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

9 голосов
/ 25 марта 2011

Я бы, вероятно, преобразовал вектор упорядочений в хэш-карту для быстрого поиска индекса упорядочения, в результате чего получилось бы что-то вроде этого:

{ :c 0  :a 1 }

Есть несколько способов сделать это автоматически из последовательности/ vector (например, map с range, затем reduce в {} с assoc).Привязать результат этого (или буквальную карту выше) к локальному (с let), назовем его order-map.

Затем отфильтруйте записи исходной карты (m), чтобы включить тольковключенные в порядок:

(select-keys m order)

И поместите результат этого отфильтрованного выражения обратно в новую отсортированную карту (используя sorted-map-by), используя функцию сравнения, подобную следующей:

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

Обратите внимание, что если вы на самом деле не нуждаетесь в этом в качестве карты, и последовательность подойдет, вы можете использовать sort-by с ключевой функцией, которая использует ту же карту ордеров.

Соединяя это вместеВы получаете:

(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}
1 голос
/ 25 марта 2011

Вот простой способ сделать это:

(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), в конечном счете полагаясь на скрытые детали реализации базовых структур данных. Принятый ответ правильный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...