我有一个调整价格的功能列表和一个产品列表。 作为输出,我希望有相同的产品列表,但价格会调整。
从技术上讲,有功能列表和地图列表。 我想要实现的是将每个功能顺序应用到列表中的每个地图,同时保留初始结构
(def products
[{:id 1 :price 100}
{:id 2 :price 200}])
(defn change-price
"increase by 10 => (change-price product 10 +)"
[product amount price-func]
(update product :price #(int (price-func amount %))))
(defn adjust-price
[products]
;;fn-list is a list of price adjuster functions
(let [fn-list [#(change-price % 10 +)
#(change-price % 50 -)]]
;; so I map a function to each product
;; which applies all adjsuter functions to that product
(merge (map (fn [prod]
(map #(% prod) fn-list)) products)))
似乎我不明白如何适当地减少结果,因为我得到的是一个嵌套列表,例如
(change-price products)
=> (({:id 1, :price 110} {:id 1, :price -50})
({:id 2, :price 210} {:id 2, :price -150}))
但是我希望
({:id 1, :price 60} {:id 2, :price 160})
谢谢。
答案 0 :(得分:2)
似乎您想应用功能的组合:
(defn adjust-price
[products]
(let [fn-list [#(change-price % 10 +)
#(change-price % 50 -)]
f (apply comp fn-list)]
(map f products)))
答案 1 :(得分:1)
事情是map
不会“挤压”结果:它只是使list [n] => list [n]。
您需要的是reduce
,如下所示:
user> (let [fn-list [#(change-price % 10 +)
#(change-price % 50 -)]]
(map (fn [p] (reduce #(%2 %1) p fn-list))
products))
;;=> ({:id 1, :price -60} {:id 2, :price -160})
您还必须重写您的change-price
函数,因为这里的参数数目错误:(price-func amount %)
=> (price-func % amount)
答案 2 :(得分:1)
您不会改变传入的哈希图,因此当您按照您的方式在一个项目上调用两个不同的函数时,您将获得不同的结果。
在“调整价格”函数中,由于您正在使用“地图”来执行“更改价格”函数,因此您当前是说,运行第一个更改价格函数一次,返回一个值,然后运行第二个价格函数一次,返回一个单独的值,导致: ({:id 1, :price 110} {:id 1, :price -50})
上面的答案很好,只是想我会使用线程函数添加另一种方法来做到这一点,这样您就不必担心顺序了。
(defn adjust-price
[products]
(let [f #(-> %
(change-price 10 +)
(change-price 50 -))]
(map f products)))
记住,单线程'->'表示你将当前行(函数)的结果向下传递到下一行(函数),并将用作第一个参数
(ps。我知道这是一个旧帖子,但希望这能帮助其他人:)