改善Clojure功能

时间:2018-10-25 18:20:19

标签: clojure

我有一个同类的地图列表,如下所示

({: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))))

它可以工作,但是对于这样一个简单的任务似乎过于复杂。所以我想知道是否有一个更简单(也许更有效)的解决方案。

2 个答案:

答案 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)))