One relatively simple way is to approach this task as a recursive mapping of K-tuples of dimension N
to K-tuples of dimension M < N
. Since this is language-agnostic, the following facilities need to be available in your target language:
- Given an instance of an
N
-dim array, find N
- Given an instance of an
N
-dim array and a k < N
, find the number of items in dimension k
- Given an instance of an
N
-dim array A
and a vector of N
integers I
, get or set the item at a position defined by indexes in the vector. For example, if the vector is I = {2, 3, 4}
, there needs to be an operation for obtaining A[2, 3, 4]
from the 3-D array A
and a vector I
.
- Given a vector
D
of size M
defining dimensions, there needs to be an operation for constructing an array of M
dimensions, each dimension taking the size of the corresponding item in the vector. For example, if the vector D = {3, 4}
, there needs to be an operation that creates a 2-D array with dimensions 3 and 4.
Preprocess the request by constructing vectors F
and D
as follows:
- For each
"all"
item at position i
of the request, F[i] = -1
and D[i] = size(dimension[i])
- For each numeric item
k
at position i
of the request, F[i] = k
and D[i] = 0
.
- Create an array for the result by taking all non-fixed indexes and passing them to the array constructor (prerequisite number four above).
Now your recursive procedure should look relatively straightforward:
void RecursiveCopy(Vector F, Vector D, Array S, Vector SI, int sp, Array T, Vector TI, int tp) {
if (pos != TS.size) {
if (F[sp] != -1) {
// This is an "all" dimension
for (int i = 0 ; i != D[sp] ; i++) {
SI[sp] = i;
TI[tp] = i;
RecursiveCopy(F, D, S, SI, sp+1, T, TI, tp+1);
}
} else {
// This is a fixed dimension
SI[sp] = F[sp];
RecursiveCopy(F, D, S, SI, sp+1, T, TI, tp);
}
} else {
// Read from the source at indexes defined by vector SI
var value = S.get(SI);
// Write to the destination at indexes defined by vector TI
T.setValue(TI, value); // Prerequisite 3
}
}
Your getSubarray
would look like this:
Array getSubarray(Array S, Vector<string> request) {
Vector F = Vector[S.Size]; // The number of dimensions in A; prerequisite 1
Vector D = Vector[S.Size]; // The number of dimensions in A
Assert(request.Size == S.Size); // Request must have N items
int k = 0;
Vector resDim;
for (int i = 0 ; i != req.Size ; i++) {
if (req[i] == "all") {
k++;
F[i] = -1;
D[i] = A.dimensionOf(i); // Prerequisite 2
resDim.Add(D[i]);
} else {
F[i] = ParseInteger(req[i]);
D[i] = -1;
}
}
Array T = Array(resDim); // Prerequisite #4
Vector SI = Vector[S.Size];
Vector TI = Vector[k];
RecursiveCopy(F, D, S, SI, 0, T, TI, 0);
return T;
}