2013-03-16 78 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