reshape method
Reshapes the array to shape
.
Note: If you want the number of elements in the new shape to be the same
as the number of elements in the original array, then you can use -1
as
a placeholder for the number of elements in the new shape.
For example, if you have a 2x2 array, then you can reshape it to a 2x3 array by doing:
reshape([-1, 3]);
Warning: If the number of elements in the new shape is less than the number of elements in the original array, then the extra elements will be lost.
If the number of elements in the new shape is greater than the number of
elements in the original array, then the extra elements will be filled
with null
.
Throws an ArgumentError if the length of shape
does not match the
number of dimensions in the array.
Throws an ArgumentError if shape
contains any negative integers other
than -1
or if it contains 0.
Implementation
void reshape(List<int> shape) {
// Check that shape has the same number of dimensions as the array.
if (shape.length != numDimensions) {
throw ArgumentError('shape must have the same number of dimensions as '
'the original array\n'
'Expected: $numDimensions\n'
'Actual: ${shape.length}');
}
// Check that shape only contains positive integers.
for (int element in shape) {
if (element < 1 && element != -1) {
throw ArgumentError('shape must only contain positive integers\n'
'Actual: $shape');
}
}
/// The shape of the array before reshaping.
final List<int> currentShape = ListTools.getShape(_data);
// Replace -1 with the correct value.
for (int i = 0; i < shape.length; i++) {
if (shape[i] == -1) {
shape[i] = currentShape[i];
}
}
// If the shape is the same, then do nothing.
if (const DeepCollectionEquality().equals(currentShape, shape)) return;
// Go through each dimension and add or remove elements as needed.
for (int i = 0; i < shape.length; i++) {
// If the shape is the same, then do nothing.
if (shape[i] == currentShape[i]) continue;
/// The chunks of the array at the current dimension.
late List<NdArray> chunks;
try {
chunks = extractDimension(i);
} catch (e) {
chunks = [this];
}
/// The desired length of the current chunks.
final int desiredLength = shape[i];
for (NdArray chunk in chunks) {
// The actual length of the current chunk.
int actualLength = chunk.shape.first;
if (actualLength < desiredLength) {
// Grow the chunk.
while (actualLength < desiredLength) {
// Build the injection.
dynamic injection;
for (int k = 0; k < numDimensions - (i + 1); k++) {
injection = [injection];
}
if (injection == null) {
chunk._data.add(null);
} else {
chunk._data.add(List<dynamic>.from(injection, growable: true));
}
actualLength++;
}
} else {
// Shrink the chunk.
chunk._data.length = desiredLength;
}
}
}
}