Search code examples
rubyclojure

In clojure how to partition an array of sorted integers into contiguous partitions?


I'd like to partition an array of sorted integers into contiguous partitions.

The following ruby:

[1,2,3,8,9,10,99].slice_when { |x, y| y > x + 1 }.to_a

Outputs:

[[1, 2, 3], [8, 9, 10], [99]]

How can I do this in clojure?

I tried using partition-by, but AFAIK it only takes one argument.


Solution

  • You have to save somewhere that previous element. In this case, you can do:

    (defn slice [coll]
      (let [prev (atom (first coll))]
        (->> coll
             (partition-by #(< (inc @prev) (reset! prev %))))))
    
    (slice [1 2 3 8 9 10 99])
    => ((1 2 3) (8 9 10) (99))
    

    If you also want to provide that function, you will have to write some reduce-based solution:

    (defn slice-when [pred coll]
      (->> coll
           (reduce (fn [acc current]
                     (if-let [previous (peek (peek acc))]
                       (if (pred previous current)
                         (conj acc [current])
                         (conj (pop acc) (conj (peek acc) current)))
                       (conj acc [current])))
                   [])))
    

    Example:

    (slice-when (fn [x y] (> y (inc x))) 
                [1 2 3 8 9 10 99])
    => [[1 2 3] [8 9 10] [99]]