Dav*_*aid 6 lisp recursion clojure
在我正在研究的一个项目中,我遇到了一个有趣的问题,我对其他解决方案感到好奇.我正在阅读"The Little Schemer",所以我正在尝试一些递归技术.我想知道是否有另一种方法可以通过递归来实现这一点,并且如果有一种不使用递归的方法也感兴趣.
问题是通过获取每个第n个元素来获取序列并将其划分为seqs序列.例如这个向量:
[ :a :b :c :d :e :f :g :h :i ]
Run Code Online (Sandbox Code Playgroud)
当用n = 3分区时会产生seq
((:a :d :g) (:b :e :h) (:c :f :i))
Run Code Online (Sandbox Code Playgroud)
并且n = 4:
((:a :e :i) (:b :f) (:c :g) (:d :h))
Run Code Online (Sandbox Code Playgroud)
等等.我用两个函数解决了这个问题.第一个创建内部seqs,另一个将它们拉在一起.这是我的功能:
(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))))))
Run Code Online (Sandbox Code Playgroud)
我对于具有多个arity的partition-by-nth函数仅仅对于递归感到不满意,但是看不到另一种方式.
对于所有测试用例,这似乎都可以正常工作.这是一个不错的方法吗?太复杂了吗?有没有办法在没有递归或可能在单个递归函数中执行此操作?
谢谢你的建议.我是Clojure和Lisp的新手,所以我正在采用不同的技术.
我希望有一个更简单的递归定义更符合The Little Schemer的精神,但是下面的函数使用起来take-nth相当紧凑,因为你说你对替代方法很感兴趣:
(defn chop [coll n]
(for [i (range n)]
(take-nth n (drop i coll))))
Run Code Online (Sandbox Code Playgroud)
满足你的例子:
(chop [:a :b :c :d :e :f :g :h :i ] 3)
;= ((:a :d :g) (:b :e :h) (:c :f :i))
(chop [:a :b :c :d :e :f :g :h :i ] 4)
;= ((:a :e :i) (:b :f) (:c :g) (:d :h))
Run Code Online (Sandbox Code Playgroud)
在Clojure中,内置的库将让您惊喜不已; 当失败时,使用显式递归解决方案.这个版本也很懒; 您可能希望使用lazy-seq或loop...recur在任何"longhand"(显式递归)版本中处理大型数据集而不会破坏堆栈.