2

我在 clojure 中有一个哈希映射,其中包含一些 nil 值。我正在尝试对数据进行分组并对值求和,由于 nil 值,这给了我一个空指针。有人可以建议我如何遍历哈希映射并将所有 nil 值替换为整数 0 吗?

(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}])

谢谢

4

5 回答 5

1
(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})
于 2013-04-18T16:29:43.107 回答
1

与其用零替换 nil 值,不如考虑使用keep. 例如:

(apply + (keep :NA data))
; 10
(apply + (keep (fn [m] (when (= (:MEDAL m) "SILVER") (:EMEA m))) data))
; 2
于 2013-04-18T17:45:48.610 回答
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 需要其他治疗。

于 2013-04-19T06:31:43.447 回答
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})
于 2013-04-19T14:07:23.057 回答
0

这是另一个快速而肮脏的事情。

(defn sum-medal
[medal data]
(assoc (apply (partial merge-with (fn [& [_ _ :as vals]] (apply + (filter number? vals)))) (filter #(= (:MEDAL %) medal) data)) :MEDAL medal))
于 2013-04-19T17:43:47.247 回答