Reputation: 59
Is there a method to initialize a non-jagged array based on the rank of another array? I don't want to use dynamic things/reflection.
I was thinking I could build a jagged array from the ground up every time using recursive functions but that seems slow + I only want nice rectangular arrays such as float[,].
(Or would it be possible to iteratively create a non-jagged array?)
Basically this is what I want.
Array func(Array x)
{
int rank = x.Rank;
int[] shape = new int[rank];
for(int i = 0; i < rank; i++)
{
shape[i] = x.GetLength(i);
}
Array ret = new float[shape]; // I want to do this
// basically float[shape[0],shape[1],...] except
// I dont know the length of shape beforehand
// processing
return ret;
}
Upvotes: 0
Views: 136
Reputation: 821
If you do not consider Array.CreateInstance
(see System.Array docs) as more dynamic as your JaggedArray
implementation, you can create new array instances with the same layout with the following implementation
private static Array CreateSized<T>(Array sourceArray)
{
int[] shape = new int[sourceArray.Rank];
for (int i = 0; i < shape.Length; i++)
shape[i] = sourceArray.GetLength(i);
return Array.CreateInstance(typeof(T), shape);
}
Using CreateSized
like so
int [] a = { 1, 2, 4, 8 };
Array fa = CreateSized<float>(a);
int [,] b = { { 10, 20, 40, 80 }, {100, 200, 400, 800 } };
Array fb = CreateSized<decimal>(b);
You can use the methods GetValue
and SetValue
on your array. For writing a value into the array:
fb.SetValue((decimal)b[0, 3] * 3, 0, 3);
and for reading from the array:
fb.GetValue(0, 3)
If you know the rank at the use of CreateSized
you can cast the result and enforce compiletime verification on the number of dimensions.
var fb = (decimal[,])CreateSized<decimal>(b);
If you don't know the rank at compiletime, the compiler can't know the rank too.
You can also use dynamic
for the newly created array. Here a small example
dynamic fc = CreateSized<double>(b);
fc[0, 2] = b[0, 2] * 3.141592;
Console.WriteLine(fc[0, 2]);
Here is a dotnetfiddle version.
Upvotes: 1
Reputation: 59
Anyway, I wrote a jagged array version
public static object JaggedArray<T>(params int[] shape)
{
object[] ret = new object[shape[0]];
if(shape.Length == 1)
{
return new T[shape[0]];
} else
{
for(int i = 0; i < shape[0]; i++)
{
ret[i] = JaggedArray<T>(shape.SubArray(1, shape.Length-1));
}
}
return ret;
}
Upvotes: 0