6.4 Slicing
One common array transformation is slicing: extracting sub-arrays by picking rows from each axis independently.
(Sequenceof Integer): pick rows from an axis by index.
Slice-Dots: preserve remaining adjacent axes
Integer: remove an axis by replacing it with one of its rows.
Slice-New-Axis: insert an axis of a given length.
Create Slice objects using :: and Slice-New-Axis objects using ::new. There is only one Slice-Dots object, namely ::....
When slicing an array with n axes, unless a list of slice specifications contains ::..., it must contain exactly n slice specifications.
> (define arr (build-array #(2 3 4) (λ: ([js : Indexes]) (string-append* (map number->string (vector->list js))))))
> arr - : (Array String)
(array
#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]])
6.4.1 (Sequenceof Integer): pick rows
> (array-slice-ref arr (list '(0 1) '(0 1 2) '(0 1 2 3))) - : (Array String)
(array
#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]])
> (array-slice-ref arr (list '(1 0) '(0 1 2) '(0 1 2 3))) - : (Array String)
(array
#[#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]
#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]])
> (array-slice-ref arr (list '(0 1) '(0 2) '(0 2))) - : (Array String)
(array #[#[#["000" "002"] #["020" "022"]] #[#["100" "102"] #["120" "122"]]])
> (array-slice-ref arr (list '(0 1) '(0 1 2) '())) - : (Array String)
(array #[#[#[] #[] #[]] #[#[] #[] #[]]])
> (array-slice-ref arr (list '(0 1) '(0 1 2) '(0 0 1 2 2 3))) - : (Array String)
(array
#[#[#["000" "000" "001" "002" "002" "003"]
#["010" "010" "011" "012" "012" "013"]
#["020" "020" "021" "022" "022" "023"]]
#[#["100" "100" "101" "102" "102" "103"]
#["110" "110" "111" "112" "112" "113"]
#["120" "120" "121" "122" "122" "123"]]])
> (array-slice-ref arr (list '(1 0) '(0 1 2) (in-range 0 4 2))) - : (Array String)
(array
#[#[#["100" "102"]
#["110" "112"]
#["120" "122"]]
#[#["000" "002"]
#["010" "012"]
#["020" "022"]]])
> (define ds (array-shape arr))
> (array-slice-ref arr (list (in-range (vector-ref ds 0)) (in-range (vector-ref ds 1)) (in-range (vector-ref ds 2)))) - : (Array String)
(array
#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]])
6.4.2 Slice: pick rows in a length-aware way
As a slice specification, a Slice object acts like the sequence object returned by in-range, but either start or end may be #f.
If start is #f, it is interpreted as the first valid axis index in the direction of step. If end is #f, it is interpreted as the last valid axis index in the direction of step.
> (array-slice-ref arr (list (::) (::) (::))) - : (Array String)
(array
#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]])
> (array-slice-ref arr (list (::) (::) (:: #f #f -1))) - : (Array String)
(array
#[#[#["003" "002" "001" "000"]
#["013" "012" "011" "010"]
#["023" "022" "021" "020"]]
#[#["103" "102" "101" "100"]
#["113" "112" "111" "110"]
#["123" "122" "121" "120"]]])
> (array-slice-ref arr (list (::) (::) (:: 2 #f 1))) - : (Array String)
(array
#[#[#["002" "003"]
#["012" "013"]
#["022" "023"]]
#[#["102" "103"]
#["112" "113"]
#["122" "123"]]])
> (array-slice-ref arr (list (::) (::) (:: 1 #f 2))) - : (Array String)
(array
#[#[#["001" "003"]
#["011" "013"]
#["021" "023"]]
#[#["101" "103"]
#["111" "113"]
#["121" "123"]]])
6.4.3 Slice-Dots: preserve remaining axes
As a slice specification, a Slice-Dots object represents any number of leftover, adjacent axes, and preserves them all.
> (array-slice-ref arr (list ::... (:: 1 #f 2))) - : (Array String)
(array
#[#[#["001" "003"]
#["011" "013"]
#["021" "023"]]
#[#["101" "103"]
#["111" "113"]
#["121" "123"]]])
> (array-slice-ref arr (list '(0) ::...)) - : (Array String)
(array
#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]])
> (array-slice-ref arr (list ::... '(1) ::...)) - : (Array String)
(array #[#[#["001"] #["011"] #["021"]] #[#["101"] #["111"] #["121"]]])
> (array-slice-ref arr (list ::... '(1))) - : (Array String)
(array #[#[#["001"] #["011"] #["021"]] #[#["101"] #["111"] #["121"]]])
> (array-slice-ref arr (list ::... '(1) '(1) '(1))) - : (Array String)
(array #[#[#["111"]]])
> (array-slice-ref arr (list '(1) ::... '(1) '(1))) - : (Array String)
(array #[#[#["111"]]])
> (array-slice-ref arr (list '(1) '(1) ::... '(1))) - : (Array String)
(array #[#[#["111"]]])
> (array-slice-ref arr (list '(1) '(1) '(1) ::...)) - : (Array String)
(array #[#[#["111"]]])
6.4.4 Integer: remove an axis
All of the slice specifications so far preserve the dimensions of the array. Removing an axis can be done by using an integer as a slice specification.
> (array-slice-ref arr (list 0 ::...)) - : (Array String)
(array
#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]])
> (array-slice-ref arr (list (::) 1 ::...)) - : (Array String)
(array #[#["010" "011" "012" "013"] #["110" "111" "112" "113"]])
> (array-slice-ref arr (list ::... 1 (::))) - : (Array String)
(array #[#["010" "011" "012" "013"] #["110" "111" "112" "113"]])
6.4.5 Slice-New-Axis: add an axis
As a slice specification, (::new dk) inserts dk into the resulting array’s shape, in the corresponding axis position. The new axis has length dk, which must be nonnegative.
> (array-slice-ref arr (list (::new) ::...)) - : (Array String)
(array
#[#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]]])
> (array-slice-ref arr (list (::new 2) ::...)) - : (Array String)
(array
#[#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]]
#[#[#["000" "001" "002" "003"]
#["010" "011" "012" "013"]
#["020" "021" "022" "023"]]
#[#["100" "101" "102" "103"]
#["110" "111" "112" "113"]
#["120" "121" "122" "123"]]]])
> (array-slice-ref arr (list (::) (::new 0) ::...)) - : (Array String)
(array #[#[] #[]])