2009-07-25 7 views
10

클로저에 양방향지도를 구현하는 가장 좋은 방법은 무엇입니까? (양방향지도에 의하면, A-> B 및 B-> A 액세스를 모두 제공 할 수있는 연관지도를 의미하므로 실제로는 값 자체가 반대 방향으로가는 열쇠가됩니다.)클로저에 양방향지도가 있습니까?

I 각 방향으로 하나씩 두 개의지도를 설정할 수 있다고 가정 해 봅시다. 그러나이 일을하는 데 더 관용적 인 방법이 있습니까?

나는 우리가 두 개의 키가 동일한 값으로 매핑 할 수 없다고 암시하는 전단 사 함수를 원하는 경우, 그 조건이 부과되지 않는 경우에 모두 관심이 있어요.

답변

12

Apache commons에있는 컬렉션 중 하나와 같이 언제든지 Java 라이브러리를 사용할 수 있습니다. 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") 

어떤 것들은, assocdissoc처럼,하지만 작동하지 않으며 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 
+1

감사합니다. 도움이됩니다. 나는 clojure 네이티브 옵션을 선호하기 때문에 두 번째 아이디어는 내가 시도할만한 것입니다. –

3

는 대부분의 경우, 난 괜찮아 다음 작품을 발견했습니다

(defn- bimap 
    [a-map] 
    (merge a-map (clojure.set/map-invert a-map))) 

이 단순히 새로운 맵에 반전지도 원래지도를 병합합니다 다음 일반지도 작업을 사용할 수 있습니다 그 결과.

빠르고 쉽지만 분명히 키 중 하나라도 값과 같거나 a-map의 값이 고유하지 않은 경우이 구현을 피해야합니다.

1

다음과 같이 우리는이 문제를 재구성 할 수 있습니다
우리는 신속하게 ab 모두 튜플을 조회 할 수 있도록하려는 튜플 ([a1 b1] [a2 b2] ...)의 목록을 감안할 때. 그래서 우리는 매핑이 a -> [a b]b -> [a b]이되기를 바랍니다. 즉, 이상 튜플 을 공유 할 수 있습니다. 그리고 구현을 생각하면 두 컬럼 모두에 의해 인덱스 된 컬럼 A와 컬럼 B가있는 메모리 내부 데이터베이스 테이블이라는 것이 명백해진다.

가벼운 메모리 내 데이터베이스 만 사용할 수 있습니다.

미안 해요, 특정 무언가를 추천하기에 충분 자바 플랫폼에 익숙하지 않다. 원인이 Datomic인데,이 특별한 경우에는 과도한 행동 일 수 있습니다. 반면에 브라이언의 답변에 대한 귀하의 의견을 토대로 당신에게 바람직하지 않은 불변성이 있습니다.