2013-04-18 43 views
1

我在clojure中有一個散列映射,它包含一些零值。我試圖對數據進行分組並對其進行求和,由於零值,這給了我一個空指針。有人可以請告訴我如何迭代哈希映射並用整數0替換所有的零值?在散列映射中用零替換nil值

(def data [{:MEDAL "SILVER" :EMEA 1 :NA nil :ASPAC 3} 
     {:MEDAL "GOLD" :EMEA 1 :NA 2 :ASPAC 3} 
     {:MEDAL "GOLD" :EMEA nil :NA 2 :ASPAC nil} 
     {:MEDAL "BRONZE" :EMEA nil :NA 2 :ASPAC 3} 
     {:MEDAL "SILVER" :EMEA 1 :NA 2 :ASPAC 3} 
     {:MEDAL "GOLD" :EMEA 1 :NA nil :ASPAC nil} 
     {:MEDAL "BRONZE" :EMEA 1 :NA 2 :ASPAC 3}]) 

感謝

回答

0
(map (fn [m] 
     (into {} 
     (map (fn [[k v]] 
       [k (if (nil? v) 0 v)]) m))) 
    data) 
=> ({:EMEA 1, :NA 0, :MEDAL "SILVER", :ASPAC 3} 
    {:EMEA 1, :NA 2, :MEDAL "GOLD", :ASPAC 3} 
    {:EMEA 0, :NA 2, :MEDAL "GOLD", :ASPAC 0} 
    {:EMEA 0, :NA 2, :MEDAL "BRONZE", :ASPAC 3} 
    {:EMEA 1, :NA 2, :MEDAL "SILVER", :ASPAC 3} 
    {:EMEA 1, :NA 0, :MEDAL "GOLD", :ASPAC 0} 
    {:EMEA 1, :NA 2, :MEDAL "BRONZE", :ASPAC 3}) 
+1

編輯,以'(如(無?V)0 V)',而不是'(或V 0)''因爲(或假0)'返回0 – ToBeReplaced

+0

@ToBeReplaced您的編輯被拒絕出於某種原因到我看到它的時候 - 所以我把它複製了,因爲它顯然更正確。 –

1

而不是替換用零的零值,你可能會考慮使用keep他們只是工作。例如:

(apply + (keep :NA data)) 
; 10 
(apply + (keep (fn [m] (when (= (:MEDAL m) "SILVER") (:EMEA m))) data)) 
; 2 
0

您可以使用fnil

(->> data 
    (apply merge-with conj (zipmap [:EMEA :NA :MEDAL :ASPAC] (repeat []))) 
    (reduce-kv #(assoc %1 %2 (reduce (fnil + 0 0) 0 %3)) {})) 

很明顯:MEDAL需要等治療。

0

我假設你想通過:MEDAL分組數據,然後添加EMEA,ASPAC等,對嗎?

;; Helper function 
(defn batch-hashmaps 
    "Applies operation on values of keys in maps. filterf filters valid values. 
Example: (batch-hashmaps + [:b :c] number? {:a 30, :b 50, :c :cheese} {:b 30, :c 40}) 
=> {:b 80, :c 40}" 
    [operation keys filterf & maps] 
    (apply conj {} 
      (for [key keys] 
      [key (apply operation (filter filterf (map #(key %) maps)))]))) 

(for [medal (set (map #(:MEDAL %) data))] 
    (assoc (apply (partial batch-hashmaps + [:EMEA :NA :ASPAC] number?) (filter #(= medal (:MEDAL %)) data)) :MEDAL medal)) 

這應該是期望的結果:

({:MEDAL "GOLD", :EMEA 2, :NA 4, :ASPAC 3} 
{:MEDAL "SILVER", :EMEA 2, :NA 2, :ASPAC 6} 
{:MEDAL "BRONZE", :EMEA 1, :NA 4, :ASPAC 6}) 
0

這裏有另外一個快速和骯髒的東西。

(defn sum-medal 
[medal data] 
(assoc (apply (partial merge-with (fn [& [_ _ :as vals]] (apply + (filter number? vals)))) (filter #(= (:MEDAL %) medal) data)) :MEDAL medal))