【问题标题】:Reshape c# array in place就地重塑 c# 数组
【发布时间】:2018-07-18 11:50:15
【问题描述】:

可能存在不依赖于数组秩的数组操作。迭代器也不总是合适的解决方案。给定数组

double[,] myarray = new double[10,5];

最好实现以下工作流程:

  1. 将 Rank>1 的数组重塑为 rank=1 且元素数量相同的线性数组。这应该发生在适当的位置以提高运行时效率。不允许复制。
  2. 仅将重构后的数组传递给为 Rank=1 数组定义的方法。例如Array.copy()
  3. 将结果数组重塑为原始等级和维度。

关于这个话题有一个类似的问题:How to reshape array in c#。那里的解决方案使用 BlockCopy() 进行内存复制操作。

我的问题是: 这种重塑可以不用内存拷贝来实现吗?或者甚至是临时的方式,比如在数据上创建一个新视图?

【问题讨论】:

  • 我认为你在这里要求一些不可能的事情......如果你想“重塑数组”那么(AFAIK)你总是需要复制元素从当前数组到新的“重构”数组...如果“不允许复制”,那么您不能“重构”/转换数组。
  • 通过要求它“不复制”完成,您实际上是在要求一个数组为另一个数组起别名。这在托管代码中是不允许的。当然,您可以使用不安全代码并获得一个指针 (fixed (double* myflatarray = myarray)),但您不会有一个可以传递给其他函数的数组。如果您编写函数以接受Span<double> 而不是数组,则可以使指针“安全”(new Span<double>(myflatarray, myarray.Length)),但您仍然没有实际的数组。 (这只是为了排名第一——我不知道你会如何回来。)
  • @Jeroen:如果接下来几天没有其他人提出解决方案,我建议您将澄清声明复制到答案中。

标签: c# arrays


【解决方案1】:

这里的措辞有点难,但指针unsafefixed 肯定会起作用。无内存拷贝,直接访问,加椒盐调味

CLR 只是不会让您随意转换数组,您能想到的任何其他方法都需要分配一个新数组并进行复制(您可以快速解决这个问题)。唯一可能的方法是使用固定的,这将为您提供连续的一维数组。

unsafe public static void SomeMethod(int* p, int size)
{
   for (var i = 0; i < 4; i++)
   {
      //Perform any linear operation
      *(p + i) *= 10;
   }
}
...

var someArray = new int[2,2];
someArray[0, 0] = 1;
someArray[0,1] = 2;
someArray[1, 0] = 3;
someArray[1, 1] = 4;

//Reshape an array to a linear array 
fixed (int* p = someArray)
{
     SomeMethod(p, 4);
}

//Reshape result array to original rank and dimensions.

for (int i = 0; i < 2; i++)
{
   for (int j = 0; j < 2; j++)
   {
      Console.WriteLine(someArray[i, j]);
   }
}

输出

10
20
30
40

【讨论】:

  • @GeorgW。当然可以,只需使用指针和大小即可。任何其他方式都需要一个副本,它就是它的方式
猜你喜欢
  • 2020-06-10
  • 2017-11-10
  • 2016-10-15
  • 2018-07-17
  • 2011-09-25
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
相关资源
最近更新 更多