私が取り組んでいるプロジェクトで、他の解決策について知りたい興味深い問題に遭遇しました。「TheLittleSchemer」を読んでいる最中なので、再帰的な手法を試しています。再帰を使ってこれを行う別の方法があるかどうか疑問に思っています。また、再帰を使用しないアプローチがあるかどうかにも興味があります。
問題は、シーケンスを取得し、n番目ごとの要素を取得することによってシーケンスをseqのシーケンスに分割することです。たとえば、このベクトル:
[ :a :b :c :d :e :f :g :h :i ]
n = 3で分割すると、seqが生成されます
((:a :d :g) (:b :e :h) (:c :f :i))
n = 4の場合:
((:a :e :i) (:b :f) (:c :g) (:d :h))
等々。私は2つの関数を使用してこれを解決しました。1つ目は内部シーケンスを作成し、もう1つはそれらをまとめます。これが私の関数です:
(defn subseq-by-nth
"Creates a subsequence of coll formed by starting with the kth element and selecting every nth element."
[coll k n]
(cond (empty? coll) nil
(< (count coll) n) (seq (list (first coll)))
:else (cons (nth coll k) (subseq-by-nth (drop (+ n k) coll) 0 n))))
(defn partition-by-nth
""
([coll n]
(partition-by-nth coll n n))
([coll n i]
(cond (empty? coll) nil
(= 0 i) nil
:else (cons (subseq-by-nth coll 0 n) (partition-by-nth (rest coll) n (dec i))))))
再帰のためだけに複数のアリティを持つpartition-by-nth関数に完全に満足しているわけではありませんが、別の方法を見つけることはできませんでした。
これは、すべてのテストケースで問題なく機能するようです。これはまともなアプローチですか?複雑すぎませんか?再帰なしで、またはおそらく単一の再帰関数でこれを行う方法はありますか?
提案をありがとう。私はClojureとLispの両方に慣れていないので、さまざまなテクニックを習得しています。