操纵两个矢量的地图在clojure

时间:2018-04-06 06:00:01

标签: clojure

我需要实现一个带有两个映射向量的函数,并返回一种组合的一个映射向量。详情如下:

输入1: [{:id 1 :car "A" :price 10}{:id 2 :car "B" :price 20}{:id 3 :car "C" :price 30}]

输入2: [{:id 4 :car "A" :price 5}{:id 5 :car "B" :price 30}{:id 6 :car "D" :price 40}]

输出: [{:id 4 :car "A" :price 5} {:id 2 :car "B" :price 20} {:id 3 :car "C" :price 30} {:id 6 :car "D" :price 40}]

也就是说,如果:car相同,请选择最低价格,或直接将:id添加到输出中。

我已经考虑使用map来获取嵌套循环中的每个值,但我相信这不是一个很好的方法。然后我学习了类似clojure.walkjuxt的内容,但它们看起来很花哨,需要更多解释。

我认为另一种可能的抽象解决方案是将它们连在一起,并使用标记检查矢量中的每个地图以检查价格。拿起最小的并移除较大的。

我希望你能帮助我,非常感谢你!

1 个答案:

答案 0 :(得分:4)

执行此操作的一种方法是按:car对项目进行分组,然后找到每个组的最低价格值:

user> (->> (concat data1 data2)
           (group-by :car)
           vals
           (map #(apply min-key :price %)))

;;=>({:id 4, :car "A", :price 5} {:id 2, :car "B", :price 20} {:id 3, :car "C", :price 30} {:id 6, :car "D", :price 40})

您也可以使用reduce进行一次传递,这有点冗长,但应该有更好的效果:

(defn process [& colls]
  (vals (reduce (fn [acc {car :car :as item}]
                  (if (acc car)
                    (update acc car (partial min-key :price) item)
                    (assoc acc car item)))
                {}
                (apply concat colls))))

user> (process data1 data2)
;;=> ({:id 4, :car "A", :price 5} {:id 2, :car "B", :price 20} {:id 3, :car "C", :price 30} {:id 6, :car "D", :price 40})