partition-by

added
1.2

ns
clojure.core

type
function

(partition-by f) (partition-by f coll)

Applies f to each value in coll, splitting it each time f returns a
new value.  Returns a lazy seq of partitions.  Returns a stateful
transducer when no collection is provided.

                user=> (partition-by #(= 3 %) [1 2 3 4 5])
((1 2) (3) (4 5))
            
                user=> (partition-by odd? [1 1 1 2 2 3 3])
((1 1 1) (2 2) (3 3))

user=> (partition-by even? [1 1 1 2 2 3 3])
((1 1 1) (2 2) (3 3))

            
                ;; (this is part of a solution from 4clojure.com/problem 30)
user=> (partition-by identity "Leeeeeerrroyyy")
((\\L) (\\e \\e \\e \\e \\e \\e) (\\r \\r \\r) (\\o) (\\y \\y \\y))
            
                ;; Note that previously created 'bins' are not used when same value is seen again
user=> (partition-by identity "ABBA")
((\\A) (\\B \\B) (\\A))

;; That is why you use group-by function if you want all the the same values in the same 'bins' :) 
;; Which gives you a hash, but you can extract values from that if you need.

(group-by identity "ABBA")
=> {\\A [\\A \\A], \\B [\\B \\B]}
            
                ;; Arbitrary partitioning
(let [seen (atom true)]
  (partition-by #(cond
                  (#{1} %) (reset! seen (not @seen))
                  (or (and (string? %)
                           (< (count %) 2))
                      (char? %)) "letter"
                  (string? %) "string"
                  (#{0} %) 0
                  (vector? %) (count %)
                  :else "rest")
                [1 1 1 2 3 nil "a" \\l 0 4 5 {:a 1} "bc" "aa" "k" [0] [1 1] [2 2]]))
;;=> ((1) (1) (1) (2 3 nil) ("a" \\l) (0) (4 5 {:a 1}) ("bc" "aa") ("k") ([0]) ([1 1] [2 2]))
            
                user=> (partition-by count ["a" "b" "ab" "ac" "c"])

;;=> (("a" "b") ("ab" "ac") ("c"))