将函数应用于序列的每个第n个元素的巧妙方法?

时间:2012-04-26 01:58:53

标签: clojure functional-programming

将函数映射到序列中每个第n个元素的简洁方法是什么?像(map-every-nth fn coll n)这样的东西,它只返回原始序列,只有每个第n个元素被转换,例如(map-every-nth inc(范围16)4)将返回(0 1 2 4 4 5 6 8 8 9 10 12 12 13 14 16)

3 个答案:

答案 0 :(得分:11)

试试这个:

(defn map-every-nth [f coll n]
  (map-indexed #(if (zero? (mod (inc %1) n)) (f %2) %2) coll))

(map-every-nth inc (range 16) 4)
> (0 1 2 4 4 5 6 8 8 9 10 12 12 13 14 16)

答案 1 :(得分:2)

我建议这比接受的答案更简单,更清洁:

(defn map-every-nth [f coll n]
  (map f (take-nth n coll)))

这是一个方便的人知道:http://clojuredocs.org/clojure_core/clojure.core/take-nth

答案 2 :(得分:0)

我个人更喜欢这个解决方案:

(defn apply-to-last [f col] (concat (butlast col) (list (f (last col)))))
(apply concat (map #(apply-to-last (fn [x] (* 2 x)) %) (partition 4 (range 16))))

或作为一项功能:

(defn apply-to-last [f col] (concat (butlast col) (list (f (last col)))))
(defn map-every-nth [f col n] (apply concat (map #(apply-to-last f %) (partition n col))))
(map-every-nth (fn [x] (* 2 (inc x))) (range 16) 4)
; output: (0 1 2 8 4 5 6 16 8 9 10 24 12 13 14 32)

请注意,这很容易导致apply-to-firstapply-to-secondapply-to-third能够控制映射每个第n个元素的“开始”。

我不知道上面编写的代码的性能,但它对我来说似乎更为惯用。