(subseq sc test key) (subseq sc start-test start-key end-test end-key)
sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true
;; Note, that collection passed to subseq must implement Sorted.
;; Just passing a collection that has been sorted is not enough.
user=> (subseq [1 2 3 4] > 2)
java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.Sorted (NO_SOURCE_FILE:0)
user=> (subseq (sorted-set 1 2 3 4) > 2)
(3 4)
;; Example of getting a subsequence of hashmaps sorted by key :a and
;; secondarily :b.
(defn compare-ab [x y]
(compare [(get x :a) (get x :b)]
[(get y :a) (get y :b)]))
(def ss-ab (apply sorted-set-by compare-ab
[{:a 42 :b 5000}
{:a 1 :b 2}
{:a 99 :b -1000}
{:a -1 :b 7}]))
user=> ss-ab
#{{:a -1, :b 7} {:a 1, :b 2} {:a 42, :b 5000} {:a 99, :b -1000}}
;; Select all maps whose key :a is greater than 5.
user=> (subseq ss-ab > {:a 5})
({:a 42, :b 5000} {:a 99, :b -1000})
;; If you use the 6 input form of this function, start-test should be > or
;; >= and the end-test should be < or <=. The other forms don't give you
;; an error, but don't give you what you expect, either. This is all based
;; on experimentation. I don't see this documented.
;; This suggests that there are no items in my set between 9 and 2.
user=> (subseq (sorted-set 1 2 3 4 5 6 7 8 9 0) < 9 > 2)
;; => ()
;; This correctly lists all items in my set between 2 and 9.
user=> (subseq (sorted-set 1 2 3 4 5 6 7 8 9 0) > 2 < 9)
;; => (3 4 5 6 7 8)
;; Again, this is not just the "and" of the two conditions. Lots of items
;; in my set are #(and (% > 2) (% > 6)) but this returns nothing. "> 2"
;; means skip to the first item that is #(% > 2). So we jump directly to 3.
;; "> 6" means to stop looking as soon as we find an item where #(% > 6) is
;; false. 3 <= 6, so we get the empty sequence.
user=> (subseq (sorted-set 1 2 3 4 5 6 7 8 9 0) > 2 > 6)
;; => ()
;; This works as expected, returning everything where #(and (% >= 2) (% <= 4)).
;; That is to say it returns everything between 2 and 4, inclusive.
user=> (subseq (sorted-set 1 2 3 4 5 6 7 8 9 0) >= 2 <= 4)
;; => (2 3 4)
;; Naïvely you might expect this to give you the same results as the previous
;; statement. Clearly the result is not the same. I'm not sure what's going
;; on under the hood here. It's jumping directly to 4 as if I'd said ">= 4"
;; rather than "<= 4". (Looks like a bug in Clojure to me!) Then it
;; continued to the end because all of the remaining items were #(% >= 2).
user=> (subseq (sorted-set 1 2 3 4 5 6 7 8 9 0) <= 4 >= 2)
;; => (4 5 6 7 8 9)
user=> *clojure-version*
;; => {:major 1, :minor 8, :incremental 0, :qualifier nil}
;; This one at least makes sense. It jumps directly to the first item that
;; satisfies the first test and continues until the second item is false.
user=> (subseq (sorted-set 1 2 3 4 5 6 7 8 9 0) >= 4 >= 2)
;; => (4 5 6 7 8 9)