Clojure将函数列表应用于参数列表
我有一个调整价格的功能列表和一个产品列表。 作为一种产出,我希望有相同的产品清单,但价格有所调整 从技术上讲,有一个功能列表和一个地图列表。 我试图实现的是将每个函数顺序地应用于列表中的每个映射,同时保留初始结构Clojure将函数列表应用于参数列表,clojure,Clojure,我有一个调整价格的功能列表和一个产品列表。 作为一种产出,我希望有相同的产品清单,但价格有所调整 从技术上讲,有一个功能列表和一个地图列表。 我试图实现的是将每个函数顺序地应用于列表中的每个映射,同时保留初始结构 (def products [{:id 1 :price 100} {:id 2 :price 200}]) (defn change-price "increase by 10 => (change-price product 10 +)" [product
(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})
提前谢谢。问题是
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})
此外,您还必须重写
更改价格
函数,因为这里的参数数错误:(价格函数金额%)
=>(价格函数金额%)
问题是映射
不会“挤压”结果:它只是生成列表[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})
此外,您还必须重写
更改价格
函数,因为此处的参数数目错误:(价格函数金额%)
=>(价格函数百分比金额)
似乎您要应用函数的组合:
(defn adjust-price
[products]
(let [fn-list [#(change-price % 10 +)
#(change-price % 50 -)]
f (apply comp fn-list)]
(map f products)))
似乎您希望应用函数的组合:
(defn adjust-price
[products]
(let [fn-list [#(change-price % 10 +)
#(change-price % 50 -)]
f (apply comp fn-list)]
(map f products)))
您没有对传入的hashmap进行变异,因此当您以这种方式对一个项调用两个不同的函数时,将得到不同的结果 在“调整价格”函数中,由于您使用“映射”来执行“更改价格”函数,因此您当前的意思是,运行第一个更改价格函数一次,返回一个值,然后运行第二个价格函数一次,返回一个单独的值,结果是: ({:ID1,:price 110}{:ID1,:price-50}) 上面的答案很好,只是我想我应该添加另一种方法来使用线程函数来实现它,这样您就不必担心顺序了
(defn adjust-price
[products]
(let [f #(-> %
(change-price 10 +)
(change-price 50 -))]
(map f products)))
请记住,单线程'->'表示将当前行(函数)的结果向下传递到下一行(函数),并将其用作第一个参数
(顺便说一句,我知道这是一篇老文章,但希望这能在将来帮助其他人:)你没有改变传入的hashmap,所以当你以这种方式对一个项目调用两个不同的函数时,你会得到不同的结果 在“调整价格”函数中,由于您使用“映射”来执行“更改价格”函数,因此您当前的意思是,运行第一个更改价格函数一次,返回一个值,然后运行第二个价格函数一次,返回一个单独的值,结果是: ({:ID1,:price 110}{:ID1,:price-50}) 上面的答案很好,只是我想我应该添加另一种方法来使用线程函数来实现它,这样您就不必担心顺序了
(defn adjust-price
[products]
(let [f #(-> %
(change-price 10 +)
(change-price 50 -))]
(map f products)))
请记住,单线程'->'表示将当前行(函数)的结果向下传递到下一行(函数),并将其用作第一个参数
(注:我知道这是一个老帖子,但希望这能在将来帮助别人:)谢谢;这也是一个完全有效的解决方案。请注意,虽然此解决方案在这种特定情况下工作正常,但它将从右向左应用函数(这是正常的,因为x+10-50==x-10+50),可能会在顺序重要的情况下导致一些混乱。在这种情况下,您可能需要
(应用comp(反向fn列表))
谢谢;这也是一个完全有效的解决方案。请注意,虽然此解决方案在这种特定情况下工作正常,但它将从右向左应用函数(这是正常的,因为x+10-50==x-10+50),可能会在顺序重要的情况下导致一些混乱。在这种情况下,您可能需要(应用comp(反向fn列表))