2013-12-19 39 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"]} 
相關問題