【问题标题】:Neat way to apply a function to every nth element of a sequence?将函数应用于序列的每个第 n 个元素的巧妙方法?
【发布时间】:2012-04-26 01:58:52
【问题描述】:

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

【问题讨论】:

    标签: clojure functional-programming


    【解决方案1】:

    试试这个:

    (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)
    

    【讨论】:

    • 谢谢我意识到它是多么微不足道,以及我在发布后不久之前是如何做到的!
    【解决方案2】:

    我建议这比公认的答案更简单、更清晰:

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

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

    【讨论】:

    • 快了!那只会返回 coll 的第 n 个成员,而我要求通过 f 映射每个 nth 的整个 coll,所以:(defn map-every-nth [f coll n] (mapcat cons (map f (take-nth n coll )) (map rest (partition n coll)) ))
    • => (map-every-nth inc (范围 16) 4) (1 1 2 3 5 5 6 7 9 9 10 11 13 13 14 15) ;干杯!您的替代方案会带来一个不错的解决方案!
    • 哎呀!刚刚注意到我是那里的一个元素......哦! take-nth 从零开始......不是我所期望的,但原理是一样的
    • 哦,我明白了……抱歉,这个答案不是你要找的。​​span>
    【解决方案3】:

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

    (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 个元素的“开始”。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-20
      • 1970-01-01
      • 2013-08-28
      • 2011-03-20
      • 1970-01-01
      • 2014-09-24
      • 1970-01-01
      相关资源
      最近更新 更多