Move partition function into the Array module

Since the function is generic over arrays, it makes more sense to house
it here.

I've also fixed an issue with its definition whereby we produced extra
empty arrays when n was greater than the original array length. We now
return an array of a length that matches precisely the number of
partitions with values we're able to create.
This commit is contained in:
Scott Olsen 2020-02-16 15:57:38 -05:00
parent ea1505779d
commit d3f99487db
2 changed files with 38 additions and 18 deletions

View File

@ -355,4 +355,40 @@ It will create a copy. If you want to avoid that, consider using [`endo-filter`]
(set! result true)
(break))))
result))
(doc partition
"Partitions an array `arr` into an array of arrays of length `n`
sequentially filled with the `arr`'s original values.
This function will fill partitions until `arr` is exhuasted.
If `n` is greater than or equal to the length of `arr`, the result of this
function is an array containing a single array of length `n`.
For example:
```clojure
(Array.partition &[1 2 3 4] 2)
=> [[1 2] [3 4]]
(Array.partition &[1 2 3 4] 3)
=> [[1 2 3] [4]]
(Array.partition &[1 2 3 4] 6)
=> [[1 2 3 4]]
```")
(sig partition (Fn [(Ref (Array a) b) Int] (Array (Array a))))
(defn partition [arr n]
(let [len (+ (mod (Array.length arr) n) (/ (Array.length arr) n))]
(let-do [x 0
y 0
a []]
;; We use while since we're doing custom incrementation of x
;; dealing with the extra increment implicitly called by for is messier
(while (< x (Array.length arr))
(do
(set! y (+ x n))
(when (> y (Array.length arr))
(set! y (Array.length arr)))
(set! a (push-back a (Array.slice arr x y)))
(set! x y)))
a)))
)

View File

@ -56,22 +56,6 @@
@(Array.unsafe-nth bs 3) @(Array.unsafe-nth bs 2)
@(Array.unsafe-nth bs 1) @(Array.unsafe-nth bs 0))))
(sig partition (Fn [(Ref (Array a) b) Int] (Array (Array a))))
(defn partition [arr partition-len]
(let [len (+ (mod (Array.length arr) partition-len) (/ (Array.length arr)
partition-len))]
(let-do [x 0
y 0
a (Array.allocate len)]
(for [i 0 len]
(do
(set! y (+ x partition-len))
(when (> y (Array.length arr))
(set! y (Array.length arr)))
(Array.aset-uninitialized! &a i (Array.slice arr x y))
(set! x y)))
a)))
(doc byte-seq->int8-seq-unsafe
"Interprets a sequence of bytes as a sequence of int8 values.
**This operation is unsafe.**")
@ -101,7 +85,7 @@
**This operation is unsafe.**")
(sig byte-seq->int32-seq (Fn [Order (Ref (Array Byte) a)] (Array Int)))
(defn byte-seq->int32-seq [order bs]
(let [partitions (partition bs 4)
(let [partitions (Array.partition bs 4)
f (fn [b] (bytes->int32-unsafe order b))]
(Array.copy-map &f &partitions)))
@ -110,7 +94,7 @@
**This operation is unsafe.**")
(sig byte-seq->int64-seq (Fn [Order (Ref (Array Byte) a)] (Array Int)))
(defn byte-seq->int64-seq [order bs]
(let [partitions (partition bs 8)
(let [partitions (Array.partition bs 8)
f (fn [b] (bytes->int64-unsafe order b))]
(Array.copy-map &f &partitions)))