2013-03-16 162 views
2

我已經哈希地圖Clojure中:扭轉哈希映射Clojure中

{"key1" "value1"} {"key2" "value2"} {"key3" "value1"} 

,我需要將其轉換成

{"value1" {"key1" "key3"}} {"value2" {"key2"}} 

哈希表這樣做的任何Clojure的方式嗎?

clojure.set/map-invert不會像覆蓋重複值一樣工作。

回答

4
(def m {"key1" "value1" "key2" "value2" "key3" "value1"}) 

(let [g (group-by val m) 
     vals (map #(map first %) (vals g))] 
    (zipmap (keys g) vals)) 
;;=> {"value2" ("key2"), "value1" ("key1" "key3")} 
1

請嘗試以下操作,我沒有REPL來測試,它可能與原始答案略有不同,但是,您可以使用它來獲取所需內容。

(group-by #(val (first %)) {"key1" "value1"} {"key2" "value2"} {"key3" "value1"}) 
1

你的問題很混亂。首先你說過你有散列圖,你實際擁有的例子是許多散列圖,或者如果你真的是一個散列圖,那麼你的例子是不正確的,因爲它應該是{"key1" "value1" "key2" "value2" "key3" "value1"}。其次,需要的輸出是奇怪的,因爲哈希映射中的值表示爲映射本身,但最後一個值僅僅是散列映射中的單個值,這顯然是不可能的,所以我想你的意思是值設置(不是地圖)作爲 {"value1" #{"key1" "key3"}} {"value2" #{"key2"}}

基於這些假設,一個可能的解決辦法是:

(->> {"key1" "value1" "key2" "value2" "key3" "value1"} 
    (group-by second) 
    (map #(-> [(%1 0) (into #{} (map first (%1 1)))])) 
    (into {})) 
1

這裏的另一種選擇:

(def maps [{"key1" "value1"} {"key2" "value2"} {"key3" "value1"}]) 

(into {} 
    (for [[k v] (group-by #(val (first %)) maps)] 
    [k (apply concat (map keys v))])) 

;=> {"value1" ("key1" "key3"), "value2" ("key2")} 
2

試試這個:

(def m {"key1" "value1" "key2" "value2" "key3" "value1"}) 

(reduce (fn [a x] (assoc a (second x) (conj (a (second x)) (first x)))) {} m) 
=> {"value2" ("key2"), "value1" ("key3" "key1")} 

注意,(可能)重複的值在列表中結束。或者,如由@ A.Webb評價建議的,上面可以簡明地寫成這樣:

(reduce (fn [a [k v]] (update-in a [v] conj k)) {} m) 
=> {"value2" ("key2"), "value1" ("key3" "key1")} 
+2

變異:'(減少(FN並[c [KV]](更新在C [V]綴k)){} m)' – 2013-03-16 19:49:10

+0

@ A.Webb太棒了!我會用你的建議更新我的答案 – 2013-03-16 19:57:17