n维数组

Sim*_*Pip 12 c# arrays multidimensional-array

我想创建一个n维的双精度数组.在编译时,维数n的数量是未知的.

我最后将数组定义为字典,键是一个对应于不同轴的int数组(所以在三维数组中,我提供[5,2,3]得到双精度(5 ,2,3)在数组中.

但是,我还需要使用从(0,0,... 0)到(m1,m2,... mn)的双精度填充字典,其中m1到mn是每个轴的长度.

我最初的想法是创建嵌套的for循环,但由于我仍然不知道我需要多少(每个维度1个),所以我无法在编译时执行此操作.

我希望我以一种可以理解的方式提出问题,但请随时让我详细说明部分内容.

the*_*oop 16

要创建n维数组,可以使用以下Array.CreateInstance方法:

Array array = Array.CreateInstance(typeof(double), 5, 3, 2, 8, 7, 32));

array.SetValue(0.5d, 0, 0, 0, 0, 0, 0);
double val1 = (double)array.GetValue(0, 0, 0, 0, 0, 0);

array.SetValue(1.5d, 1, 2, 1, 6, 0, 30);
double val2 = (double)array.GetValue(1, 2, 1, 6, 0, 30);
Run Code Online (Sandbox Code Playgroud)

要填充数组,可以使用Rank属性和GetLength方法返回当前维度的长度,使用几个嵌套的for循环来执行O(n ^ m)算法(警告 - 未经测试):

private bool Increment(Array array, int[] idxs, int dim) {
    if (dim >= array.Rank) return false;

    if (++idxs[idxs.Length-dim-1] == array.GetLength(dim)) {
        idxs[idxs.Length-dim-1] = 0;
        return Increment(array, idxs, dim+1);
    }
    return true;
}

Array array = Array.CreateInstance(typeof(double), ...);
int[] idxs = new int[array.Rank];
while (Increment(array, idxs, 0)) {
    array.SetValue(1d, idxs);
}
Run Code Online (Sandbox Code Playgroud)


Sim*_*Pip 7

快速跟进此事:

我们成功使用了Array.CreateInstance方法,但正如有人预测的那样,效率相当低,并且还会产生可读性问题.

相反,我们开发了一种方法,其中n维数组被转换为1维(正常)数组.

public static int NDToOneD(int[] indices, int[] lengths)
{
  int ID = 0;
  for (int i = 0; i < indices.Length; i++)
  {
    int offset = 1;
    for (int j = 0; j < i; j++)
{
      offset *= lengths[j];
}
    ID += indices[i] * offset;
  }
  return ID;
}

1DtoND(int[] indices, int[] arrayLengths)
{
  int[] indices = new int[lengths.Length];
  for (int i = lengths.Length - 1; i >= 0; i--)
  {
    int offset = 1;
    for (int j = 0; j < i; j++)
    {
      offset *= lengths[j];
    }
    int remainder = ID % offset;
    indices[i] = (ID - remainder) / offset;
    ID = remainder;
  }
  return indices;
}
Run Code Online (Sandbox Code Playgroud)

这实质上是将笛卡尔坐标转换为单个整数并再次转换的概括.

我们的测试没有正式化,所以我们获得的任何加速完全是轶事,但对于我的机器,它提供了大约30-50%的加速,取决于样本大小,并且代码的可读性大大提高.

希望这可以帮助任何偶然发现这个问题的人.