【问题标题】:How do I implement a lazy "reducing map" function?如何实现一个懒惰的“减少地图”功能?
【发布时间】:2011-05-14 09:01:39
【问题描述】:

我正在尝试实现“缩小地图”功能。也就是说,它应该返回一个序列,该序列由将f 应用于coll 的前两项的结果、随后将f 应用于该结果和coll 的第三项的结果等组成。

(def c [[0 0 0 0] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]])

(defn- sum-vector [v1 v2]
  (map + v1 v2))

(defn reduce-map [f coll & acc]
  (if (< (count coll) 2)
    (if (empty? acc) coll acc)
    (let [head (apply f (take 2 coll))
          tail (drop 2 coll)]
      (recur f (conj tail head) (conj acc head)))))

例如,像这样调用这个函数:

(reduce-map sum-vector c)

应该返回:

[[1 0 0 0] [1 1 0 0] [1 1 1 0] [1 1 1 1]]

(实际上,它可能也应该返回未修改的第一项,以更好地模仿map,但我可以稍后修复。)

对,现在,这就是它返回的内容:

((1 1 1 1) (1 1 1 0) (1 1 0 0) (1 0 0 0))

如何在(ny) seq 的末尾“推”?

如果我用reduce-map 替换recur,它会返回:

(((1 1 1 1) ((1 1 1 0) ((1 1 0 0) ((1 0 0 0))))))

我上面的代码中recur 和真正的递归有什么区别?

而且,有没有一种内置的,或者更好的,或者更惯用的方法来实现reduce-map?

最后,我希望输出序列是惰性的。我是否将整个内容都包裹在 lazy-seq 中?

【问题讨论】:

    标签: recursion clojure map reduce cons


    【解决方案1】:

    这听起来有点像reductions。

    关于 seq 末尾的“推”:一般 seq 没有​​“end”,参见。 (iterate inc 0).

    关于列表末尾的“推”:列表不是为此而设计的。使用向量。用[] 播种你的累加器,而不是nil。

    关于lazy-seq:使用“真”递归而不是recur。举个例子:

    (defn integer-seq
      [start]
      (lazy-seq
        (cons start (integer-seq (inc start)))))
    

    【讨论】:

    • 那是快。谢谢!
    猜你喜欢
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 2010-11-30
    相关资源
    最近更新 更多