clojure 将集合拆分为大小不断增加的块

clojure split collection in chunks of increasing size

嗨,我是 clojure 新手,

我正在尝试创建一个函数,将集合拆分成大小不断增加的块,类似于

(apply #(#(take %) (range 1 n)) col)

其中 n 是块的数量

预期输出示例: n = 4 且 col = (range 1 4)

(1) (2 3) (4)

n = 7 且 col =(范围 1 7)

(1) (2 3) (4 5 6) (7)

你可以这样使用:

(defn partition-inc
  "Partition xs at increasing steps of n" 
  [n xs] 
  (lazy-seq 
    (when (seq xs) 
      (cons (take n xs) 
            (partition-inc (inc n) (drop n xs))))))

; (println (take 5 (partition-inc 1 (range))))
; → ((0) (1 2) (3 4 5) (6 7 8 9) (10 11 12 13 14))

或者如果你想有更大的影响力,你也可以提供 大小的序列(如果通过 (iterate inc 1) for sizes:

,则与上面的行为相同
(defn partition-sizes
  "Partition xs into chunks given by sizes"
  [sizes xs]
  (lazy-seq
    (when (and (seq sizes) (seq xs))
      (let [n (first sizes)]
        (cons (take n xs) (partition-sizes (rest sizes) (drop n xs)))))))

; (println (take 5 (partition-sizes (range 1 10 2) (range))))
; → ((0) (1 2 3) (4 5 6 7 8) (9 10 11 12 13 14 15) (16 17 18 19 20 21 22 23 24))

一个急切的解决方案看起来像

(defn partition-inc [coll]
  (loop [rt [], c (seq coll), n 1]
    (if (seq c)
      (recur (conj rt (take n c)) (drop n c) (inc n))
      rt)))

另一种方法是使用一些 clojure 序列函数:

(->> (reductions (fn [[_ x] n] (split-at n x))
                 [[] (range 1 8)]
                 (iterate inc 1))
     (map first)
     rest
     (take-while seq))

;;=> ((1) (2 3) (4 5 6) (7))

另一种方法...

(defn growing-chunks [src]
  (->> (range)
       (reductions #(drop %2 %1) src)
       (take-while seq)
       (map-indexed take)
       rest))

(growing-chunks [:a :b :c :d :e :f :g :h :i])
;; => ((:a) (:b :c) (:d :e :f) (:g :h :i))