Search code examples
functional-programmingclojurepartitioning

Clojure - map a partition over a sequence


I have two collections of the same size - I have partitioned the first one and would like to apply the same partition to the second one. Is there an elegant way of doing this? I have found the following but it seems ugly...

(def x (range 50 70))
(def y [(range 5) (range 10) (range 3) (range 2)] ;my partition of 20 items

(drop-last
  (reduce (fn [a b] (concat (drop-last a)
                            (split-at (count b) (last a))))
          [x] y))

Solution

  • i would propose a slightly different approach, using the collections manipulation functions:

    (defn split-like [pattern data]
      (let [sizes (map count pattern)]
        (->> sizes
             (reductions #(drop %2 %1) data)
             (map take sizes))))
    
    user> (split-like y x)
    ;;=> ((50 51 52 53 54) (55 56 57 58 59 60 61 62 63 64) (65 66 67) (68 69))
    

    the idea is to collect corresponding tails by reductions with drop:

    user> (reductions (fn [acc x] (drop x acc)) (range 20) [1 2 3 4])
    ;;=> ((0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
    ;;    (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
    ;;    (3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
    ;;    (6 7 8 9 10 11 12 13 14 15 16 17 18 19)
    ;;    (10 11 12 13 14 15 16 17 18 19))
    

    and then just to take needed amounts from that tails:

    user> (map take [1 2 3 4] *1)
    ;;=> ((0) (1 2) (3 4 5) (6 7 8 9))