具有非零下限的二维数组的子数组
Posted
技术标签:
【中文标题】具有非零下限的二维数组的子数组【英文标题】:SubArray of a 2d array with non-zero lower bounds 【发布时间】:2021-02-04 18:27:24 【问题描述】:扩展名:
public static T[,] SubArray<T>(this T[,] values, int row_min, int row_max, int col_min, int col_max)
int num_rows = row_max - row_min + 1;
int num_cols = col_max - col_min + 1;
T[,] result = new T[num_rows, num_cols];
int total_cols = values.GetUpperBound(1) + 1;
int from_index = row_min * total_cols + col_min;
int to_index = 0;
for (int row = 0; row <= num_rows - 1; row++)
Array.Copy(values, from_index, result, to_index, num_cols);
from_index += total_cols;
to_index += num_cols;
return result;
适用于GetLowerBound(0)
和GetLowerBound(1)
等于0 的二维数组。例如如果
int[,] arr1 = new int[5, 4];
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 4; ++j)
arr1[i, j] = i + j;
var arr1sub = arr1.SubArray(2, 3, 1, 3);
那么arr1sub
是2行3列的二维数组(索引都从0开始)
3 4 5
5 6 7
现在,如果我看一下初始数组作为索引不从零开始的情况:
int[,] arr2 = (int[,])Array.CreateInstance(typeof(int), new int[] 5, 4 , new int[] 3, 1 );
for (int i = arr2.GetLowerBound(0); i <= arr2.GetUpperBound(0); ++i)
for (int j = arr2.GetLowerBound(1); j <= arr2.GetUpperBound(1); ++j)
arr2[i, j] = i - arr2.GetLowerBound(0) + j - arr2.GetLowerBound(1);
var arr2sub = arr2.SubArray(5, 6, 2, 4);
前面代码的最后一行sn -p会在该行的SubArray
扩展函数中触发异常
Array.Copy(values, from_index, result, to_index, num_cols);
对于row
等于零。
我了解二维数组 arr1
(具有从零开始的索引)在内存中的布局,但不了解二维数组 arr2
(具有非从零开始的索引)在内存中的布局方式,因此我使用Array.Copy
在这种情况下肯定是错误的,但我不明白为什么。
【问题讨论】:
【参考方案1】:您没有正确计算total_cols
和from_index
。
public static T[,] SubArray<T>(this T[,] values, int row_min, int row_max, int col_min, int col_max)
int num_rows = row_max - row_min + 1;
int num_cols = col_max - col_min + 1;
T[,] result = new T[num_rows, num_cols];
int total_cols = values.GetLength(1);
int from_index = (row_min - values.GetLowerBound(0)) * total_cols + (col_min - values.GetLowerBound(1)) + values.GetLowerBound(0);
int to_index = 0;
for (int row = 0; row <= num_rows - 1; row++)
Array.Copy(values, from_index, result, to_index, num_cols);
from_index += total_cols;
to_index += num_cols;
return result;
total_cols
是显而易见的;至于from_index
,我找不到任何相关文档,但似乎Array.Copy
中的sourceIndex
是从sourceArray.GetLowerBound(0)
开始计数,而不是从零开始计数,鉴于该指数不断增长,这一点不一定立即显而易见行和列。
【讨论】:
确实有效。我试图制作SubArray
,不仅让它返回一个从零开始的索引数组,而且(提供bool rebase
)一个数组,其行从索引row_min
开始,列从索引col_min
开始(通过用适当的T[,] result = (T[,]) Array.CreateInstance(typeof(T), new int[] num_rows, num_cols, new int[] rebase ? 0 : row_min, rebase ? 0 : col_min );
替换new
行)。在这种情况下,total_cols
和 from_index
不会更改,但 to_index
会更改,并且如果 rebase
是 false
则应该等于 col_min
但它似乎不起作用
@11house should be equal to col_min
- 反过来:int to_index = rebase ? 0 : row_min;
。正如问题中所述,Array.Copy 从sourceArray.GetLowerBound(0)
开始计数,即row_min
。以上是关于具有非零下限的二维数组的子数组的主要内容,如果未能解决你的问题,请参考以下文章