In this post, I'm using the term slice to refer to a subarray B_i
of an n-dimensional array A
such that size(B_i, d)
is 1, for some dimension d
. A
consists of size(A, d)
such slices, concatenated along dimension d
.
For example, if ndims(A)
is 6 and d
is 3, then the expressions of the form
A(:, :, i, :, :, :)
for i
in 1:size(A, d)
represent all the slices (along dimension d
) that make up A
.
The problem with an expression like A(:, :, i, :, :, :)
is that it cannot be generalized symbolically to slices along a dimension different from 3 in arrays having a number of dimensions different from 6. E.g., to get A
's slices along dimension 2, one would need a different expression, A(:, i, :, :, :, :)
. This means that such expressions are useless in code that is agnostic about the shape of some array from which slices are to be extracted.
The function below is my matlab-noob attempt to implement shape-agnostic slicing. (The name slice
is already taken, hence I called the function hslice
, short for hyperslice
.) The function's strategy is to reshape the input array into a suitable 3-d array, take the desired slice along the reshaped array's second dimension, and reshape the result to have the shape of a slice from the original input array.
function out = hslice(ndarray, d, i)
sz = size(ndarray);
pfx = sz(1:d-1); % dimensions before d
sfx = sz(d+1:end); % dimensions after d
tmp = reshape(ndarray, prod(pfx), sz(d), prod(sfx));
out = reshape(tmp(:, i, :), [pfx 1 sfx]);
end
Is there a built-in, or at least a more efficient, way to achieve the same result (in a shape-agnostic way)?
O(n)
analysis is often less useful than figuring out how to "vectorize" stuff with fast Matlab built-ins. But all these indexing, reshaping, and copy operations you're using are quite cheap, relatively speaking. And doing it in a function is fine: Because you're making a new array, there's no in-place optimization possible, and copy-on-write means passing arrays between functions is cheap. Your method should perform fine. – Andrew Jankereshape()
in particular is uber-fast, because it doesn't actually rearrange your raw primitive data in memory: it just twiddles the "dimensions" info in the header of Matlab's internal data structure (the "mxArray"), and retains a pointer to the original underlying primitive data. So your implementation here is only making a single extraction/copy of the primitive data, just like the staticA(:, :, i, :, ...)
indexing expression. – Andrew Janke