2013-12-19 42 views
3

我有一个哈希表是这样的:最好的方法来更新hashmap中的几个值?

{:key1 "aaa bbb ccc" :key2 "ddd eee" :key3 "fff ggg" :do-not-split "abcdefg hijk"} 

而且我想分裂的某些字符串得到向量:

; expected result 
{:key1 ["aaa" "bbb" "ccc"] :key2 ["ddd" "eee"] :key3 ["fff" "ggg"] :do-not-split "abcdefg hijk"} 

我用update-in三次了类似以下,但看起来很丑。

(-> my-hash (update-in [:key1] #(split % #"\s")) 
      (update-in [:key2] #(split % #"\s")) 
      (update-in [:key3] #(split % #"\s"))) 

我希望有某事像(update-all my-hash [:key1 :key2 :key3] fn)

回答

4

您可以使用reduce

user=> (def my-hash {:key1 "aaa bbb ccc" :key2 "ddd eee" :key3 "fff ggg"}) 
#'user/my-hash 
user=> (defn split-it [s] (clojure.string/split s #"\s")) 
#'user/split-it 
user=> (reduce #(update-in %1 [%2] split-it) my-hash [:key1 :key2 :key3]) 
{:key3 ["fff" "ggg"], :key2 ["ddd" "eee"], :key1 ["aaa" "bbb" "ccc"]} 
+0

'[:KEY1:键2:KEY3]'可能与替换'(钥匙我的哈希)' – mishadoff

+0

@mishadoff我认为这是他可以指定要替换哪个键OP的意图,而不是简单地所有。否则,您可以简单地使用地图族的一个功能而不是减少。 – sloth

+0

我错过了这一点,谢谢 – mishadoff

0

这是接近问题的不同方式。

想一想:如果你的字符串在列表中,你会如何处理它?

答案是,你可以使用map得到载体列表:

(map #(split % #"\s") list-of-strings) 

如果你觉得你越会的结论是你真正想要的是地图在函数到达的地图。显然map在这里不起作用,因为它仅适用于序列。

但是,有没有地图的通用版本?原来有!它被称为fmap,来自函数的概念,您现在可以忽略它。这是你将如何使用它:

(fmap my-hash #(split % #"\s")) 

看看目前的意图是如何更清晰?

唯一的缺点是fmap不是核心功能,但它可通过algo.generic库获得。

当然,如果包括一个新的图书馆感觉太多在这个阶段,你可以随时钢的源代码 - 和属性它的作者 - 从图书馆本身this link

(into (empty my-hash) (for [[k v] my-hash] [k (your-function-here v)])) 
+0

有趣。我早就想到了'fmap',但似乎我只需要改变一些值,这些值在hashmap中是少数。 – halfelf

+0

这应该没问题。你的函数会有一个谓词来检查值是否应该更新,如果没有,就返回原来的值。 – leonardoborges

2

只是映射值基于决定是否分裂的函数。

user=> (def x {:key1 "aaa bbb ccc" 
       :key2 "ddd eee" 
       :key3 "fff ggg" 
       :do-not-split "abcdefg hijk"}) 
#'user/x 

user=> (defn split-some [predicate [key value]] 
     (if (predicate key) 
      [key (str/split value #" ")] 
      [key value])) 
#'user/split-some 

user=> (into {} (map #(split-some #{:key1 :key2 :key3} %) x)) 
{:do-not-split "abcdefg hijk", :key3 ["fff" "ggg"], :key2 ["ddd" "eee"], :key1 ["aaa" "bbb" "ccc"]} 
相关问题