我有一个同类的地图列表,如下所示
({:x 1 :y 2} {:x 3 :y 5} {:x 1 :y 7} {:x 2 :y 0} {:x 3 :y -1})
我想将成对的:y
值和相等的:x
值相加。我的意思是,我想要一个函数y-adder
,如果将其应用于前面的列表就可以给出列表(顺序并不重要,它可以是集合而不是列表)
({:x 1 :y 9} {:x 3 :y 4} {:x 2 :y 0})
我写的是以下内容:
(defn y-adder [Ps]
(let [xs (set (map :x Ps))]
(let [y+ (fn [v] (apply + (map :y (filter #(= (:x %) v) Ps))))]
(map #(hash-map :x % :y (y+ %)) xs))))
它可以工作,但是对于这样一个简单的任务似乎过于复杂。所以我想知道是否有一个更简单(也许更有效)的解决方案。
答案 0 :(得分:5)
对我来说,这有点简单,但是我没有检查它是否更有效。
> (for [[k v] (group-by :x xs)] {:x k :y (apply + (map :y v))})
({:x 1, :y 9} {:x 3, :y 4} {:x 2, :y 0})
关键是group-by
:
> (group-by :x xs)
{1 [{:x 1, :y 2} {:x 1, :y 7}],
3 [{:x 3, :y 5} {:x 3, :y -1}],
2 [{:x 2, :y 0}]}
一旦获得,就很容易达到您想要的结果。
答案 1 :(得分:1)
您可以使用group-by
:
(defn y-adder [ps]
(map (fn [[x-val matches]]
{:x x-val :y (apply + (map :y matches))})
(group-by :x ps)))