怠zyな「マップを減らす」機能を実装するにはどうすればよいですか?
質問
「マップの削減」関数を実装しようとしています。つまり、適用の結果からなるシーケンスを返す必要があります f
の最初の2つのアイテムへ coll
, 、適用の結果が続きます f
その結果と3番目のアイテムに 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
?
最後に、出力シーケンスを怠zyにしたいと思います。すべてを包みますか? lazy-seq
?
解決
これは少し似ています reductions
.
配列の終わりに「プッシュ」について:一般的には「終了」はありません。 (iterate inc 0)
.
リストの最後に「プッシュ」することについて:リストはそのために設計されていません。ベクトルを使用します。アキュムレータをシードします []
, 、 いいえ nil
.
について lazy-seq
: :ではなく「True」再帰を使用します recur
. 。ここに例:
(defn integer-seq
[start]
(lazy-seq
(cons start (integer-seq (inc start)))))
所属していません StackOverflow