I want write extension method for fill multidimensional rectangular array. I know how to do it for the array with a fixed number of measurements:
public static void Fill<T>(this T[] source, T value)
{
for (int i = 0; i < source.Length; i++)
source[i] = value;
}
public static void Fill<T>(this T[,] source, T value)
{
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
source[i, j] = value;
}
public static void Fill<T>(this T[,,] source, T value)
{
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
for (int k = 0; k < source.GetLength(2); k++)
source[i, j, k] = value;
}
Can I write one fill-method for all multidimensional rectangular array?
You can change the fixed dimension parameter to an Array parameter so you can put the extension on any Array. Then I used recursion to iterate through each position of the array.
public static void Fill<T>(this Array source, T value)
{
Fill(0, source, new long[source.Rank], value);
}
static void Fill<T>(int dimension, Array array, long[] indexes, T value)
{
var lowerBound = array.GetLowerBound(dimension);
var upperBound = array.GetUpperBound(dimension);
for (int i = lowerBound; i <= upperBound; i++)
{
indexes[dimension] = i;
if (dimension < array.Rank - 1)
{
Fill(dimension + 1, array, indexes, value);
}
else
{
array.SetValue(value, indexes);
}
}
}
Here's a solution that does not use recursion (and is less complex):
public static void FillFlex<T>(this Array source, T value)
{
bool complete = false;
int[] indices = new int[source.Rank];
int index = source.GetLowerBound(0);
int totalElements = 1;
for (int i = 0; i < source.Rank; i++)
{
indices[i] = source.GetLowerBound(i);
totalElements *= source.GetLength(i);
}
indices[indices.Length - 1]--;
complete = totalElements == 0;
while (!complete)
{
index++;
int rank = source.Rank;
indices[rank - 1]++;
for (int i = rank - 1; i >= 0; i--)
{
if (indices[i] > source.GetUpperBound(i))
{
if (i == 0)
{
complete = true;
return;
}
for (int j = i; j < rank; j++)
{
indices[j] = source.GetLowerBound(j);
}
indices[i - 1]++;
}
}
source.SetValue(value, indices);
}
}
This is modeled from the System.Array.ArrayEnumerator. This implementation should have a similar level of correctness as ArrayEnumerator and (based on a few spot checks) appears to function fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With