Двунаправленная карта в clojure?

Оперативное значение, подкачивающее

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

, правая сторона присвоения является выражением, которое создает новый кортеж. Левая сторона присвоения сразу распаковывает тот (не имеющий ссылки) кортеж к именам a и b.

После присвоения, новый кортеж является не имеющим ссылки и отмечен для сборки "мусора", и значения, связанные с a и b, были подкачаны.

, Как отмечено в учебный раздел Python по структурам данных ,

Примечание, что несколько присвоение являются действительно просто комбинацией упаковки кортежа и распаковки последовательности.

11
задан Rob Lachlan 25 July 2009 в 22:27
поделиться

1 ответ

Вы всегда можете использовать для этого библиотеку Java, например одну из коллекций в Общие ресурсы Apache . TreeBidiMap реализует java.util.Map , поэтому он может быть даже последовательным без каких-либо усилий.

user> (def x (org.apache.commons.collections.bidimap.TreeBidiMap.))
#'user/x
user> (.put x :foo :bar)
nil 
user> (keys x)
(:foo)
user> (.getKey x :bar)
:foo
user> (:foo x)
:bar
user> (map (fn [[k v]] (str k ", " v)) x)
(":foo, :bar")

Некоторые вещи не будут работать, например assoc и disoc , поскольку они ожидают постоянных коллекций, а TreeBidiMap является изменяемым.

Если вы действительно хотите сделать это в родном Clojure, вы можете использовать метаданные для хранения хэша обратного направления. Это по-прежнему удвоит ваши требования к памяти и удвоит время для каждого добавления и удаления, но поиск будет достаточно быстрым и, по крайней мере, все будет объединено.

(defn make-bidi []
  (with-meta {} {}))

(defn assoc-bidi [h k v]
  (vary-meta (assoc h k v)
             assoc v k))

(defn dissoc-bidi [h k]
  (let [v (h k)]
   (vary-meta (dissoc h k)
              dissoc v)))

(defn getkey [h v]
  ((meta h) v))

Вам, вероятно, придется реализовать кучу других функций, чтобы получить полную функциональность конечно. Не уверен, насколько осуществим этот подход.

user> (def x (assoc-bidi (make-bidi) :foo :bar))
#'user/x
user> (:foo x)
:bar
user> (getkey x :bar)
:foo
13
ответ дан 3 December 2019 в 07:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: