mlu*_*own 9 clojure map-function
在本节末尾的"勇敢与真实的Clojure"中,减少了一个挑战:
如果你想要一个真正让你的头发恢复的运动,请尝试
map使用reduce
事实证明,这比我想象的要困难得多(至少对我来说是一个Clojure初学者).经过几个小时,我想出了这个:
(defn map-as-reduce
[f coll]
(reduce #(cons (f %2) %1) '() (reverse coll)))
Run Code Online (Sandbox Code Playgroud)
这是一个更好的方法吗?我特别感到沮丧的是,我必须反转输入集合才能使其正常工作.它似乎有点不雅!
Sam*_*tep 10
请记住,您可以在向量的末尾有效插入:
(defn map' [f coll]
(reduce #(conj %1 (f %2)) [] coll))
Run Code Online (Sandbox Code Playgroud)
例:
(map' inc [1 2 3])
;=> [2 3 4]
Run Code Online (Sandbox Code Playgroud)
这map'与原作之间的一个区别map是原文map返回的是一个ISeq而不是一个Seqable:
(seq? (map inc [1 2 3]))
;=> true
(seq? (map' inc [1 2 3]))
;=> false
Run Code Online (Sandbox Code Playgroud)
您可以通过组合上述实施解决这个问题map'有seq:
(defn map' [f coll]
(seq (reduce #(conj %1 (f %2)) [] coll)))
Run Code Online (Sandbox Code Playgroud)
现在最重要的区别是,虽然原始map是懒惰的,但这map'是渴望的,因为reduce是渴望.
只是为了好玩:map真的接受多个集合作为参数.这是一个扩展实现:
(defn map-with-reduce
([f coll] (seq (reduce #(conj %1 (f %2)) [] coll)))
([f coll & colls]
(let [colls (cons coll colls)]
(map-with-reduce (partial apply f)
(partition (count colls)
(apply interleave colls))))))
Run Code Online (Sandbox Code Playgroud)
在repl中:
user> (map-with-reduce inc [1 2 3])
(2 3 4)
user> (map-with-reduce + [1 2 3] [4 5] [6 7 8])
(11 14)
Run Code Online (Sandbox Code Playgroud)
小智 7
真实的地图在其集合参数上调用seq并返回一个懒惰的seq,所以也许这可以使它更接近真实的地图?
(defn my-map
[f coll]
(lazy-seq (reduce #(conj %1 (f %2)) [] (seq coll))))
Run Code Online (Sandbox Code Playgroud)
我会补充说,作为评论,但我没有声誉.:)