首页 > 代码库 > [4Clojure]解题记录-#69
[4Clojure]解题记录-#69
Difficulty: | Medium |
Topics: | core-functions |
Write a function which takes a function f and a variable number of maps. Your function should return a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) should be combined with the mapping in the result by calling (f val-in-result val-in-latter)
(= (__ * {:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5}) {:a 4, :b 6, :c 20})
(= (__ - {1 10, 2 20} {1 3, 2 10, 3 15}) {1 7, 2 10, 3 15})
(= (__ concat {:a [3], :b [6]} {:a [4 5], :c [8 9]} {:b [7]}) {:a [3 4 5], :b [6 7], :c [8 9]})
特殊限制:禁用merge-with
解(长度:100)
(fn [f & x] (reduce
(fn [m v]
(let [k (first v) w (last v)]
(if (m k)
(assoc m k (f (m k) w))
(assoc m k w)))) {} (apply concat x)))
中间过程:经历了2个版本,第一个版本比较差,后面这个比较好(短)。
基本思路是用reduce两两合并,输入方式是(apply concat x),效果:
(apply concat ‘({:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5}))
;([:a 2] [:b 3] [:c 4] [:a 2] [:b 2] [:c 5])
因此第一个reduce合并的想法是,vector of vector 与 vector 合并:
(defn my-com [f x y]
(let [u (last x) v (first u) w (first y)]
(if (= v w)
(sort-by #(first %) (conj (butlast x) [v (f (last u) (last y))]))
(sort-by #(first %) (conj x y)))))
效果:(这里需要有序的输入)
user=> (my-com + [] [:a 1]);([:a 1])
user=> (my-com + [[:a 3] [:b 4]] [:b 1]);([:a 3] [:b 5])
最后配合reduce:(reduce (partial my-com +) nil (sort-by #(first %) (concat {:a 2:b 3} {:a 2 :b 3 :c 4}))); ([:a 4] [:b 6] [:c 4]); 以及按要求输出成{:a 4, :b 3, :c 4},
(into (hash-map) (reduce (partial my-com *) nil (sort-by #(first %) (concat{:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5}))));{:a 4, :b 6, :c 20}
然后是所有函数匿名以及整合。 但是这个方法不好,因为中间通过vector的形式合并,又需要有序,因此立刻想到reduce是hash-map与vector的合并:
(defn my-com2 [f m v]
(let [k (first v) w (second v)]
(if (m k)
(assoc m k (f (m k) w))
(assoc m k w))))
user=>(my-com2 + {:a 2 :b 3} [:a 1]);{:a 3, :b 3}
user=>(reduce (partial my-com2 *) {} (apply concat ‘({:a 2, :b 3, :c 4} {:a2} {:b 2} {:c 5}))); {:c 20, :b 6, :a 4}
这次,就不需要对输出进行转换了,因为直接是目标格式的大map,最终整合,匿名时候发现,my-com2的匿名形式不需要f这个参数,因为在外层的fn[f & x]已经有了f,可以直接用:
(fn [f & x] (reduce
(fn [m v]
(let [k (first v) w (last v)]
(if (m k)
(assoc m k (f (m k) w))
(assoc m k w)))) {} (apply concat x)))
为了尽可能缩短代码,把second 换成了last,这个纯粹是为了题目,其实不是好的做法。
[4Clojure]解题记录-#69
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。