我正在尝试找到一种在clojure中实现分区(带[]填充)的方法。我认为使用循环并重复并将其映射到列表中是可行的:
(defn collect-h [v n]
(loop [i n
res []
lst v
]
(if (= 0 i)
res
(recur (dec i) (cons (first lst) res) (next lst))
)
)
)
所以问题是实现只适用于第一系列答案“(collect-h [1 2 3 4 5 6 7 8 9 10] 3)
会给((1 2 3))
”。所以我需要将它映射到整个集合并删除每个循环中的第一个n
数字,但这看起来并不高效。我想知道是否有更好的方法来解决它。
修改
所以它应该像这样工作:
(collect-h [1 2 3 4 5 6 7 8 9 10] 3) ;; ((1 2 3) (4 5 6) (7 8 9) (10))
与
相同(partition 3 3 [] [1 2 3 4 5 6 7 8 9 10])
答案 0 :(得分:5)
@Timothy-Pratley答案很好,但它不是尾递归,这意味着它会在大量收集的情况下导致堆栈溢出。这是非堆栈消费变体:
(defn my-partition [n items]
(loop [res [] items items]
(if (empty? items)
res
(recur (conj res (take n items))
(drop n items)))))
user> (my-partition 3 (range 10))
[(0 1 2) (3 4 5) (6 7 8) (9)]
答案 1 :(得分:3)
建立@ Timothy-Pratley和Clojure源代码,你也可以使用lazy-seq:
(defn partition-ghetto [n xs]
(lazy-seq (when-let [s (seq xs)]
(cons (take n s) (partition-ghetto n (drop n s))))))
答案 2 :(得分:2)
这个怎么样?
(defn partition-ghetto [n xs]
(if (seq xs)
(cons (take n xs) (partition-ghetto n (drop n xs)))
()))
(partition-ghetto 3 (range 10))
=> ((0 1 2) (3 4 5) (6 7 8) (9))
绝对不如核心版本好,但可能提供一些想法?
请注意,这个递归定义不是尾递归的,所以会为大序列吹掉堆栈,也不像大多数Clojure序列函数那样懒惰。懒惰对序列的优点是在流上操作时既不是堆栈也不是堆绑定。请参阅下面的替代答案,为这些问题提供解决方案。