#c# #arrays #multidimensional-array
#c# #массивы #многомерный массив
Вопрос:
Расширение :
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 resu<
}
хорошо работает для 2D-массивов массивов, чьи GetLowerBound(0)
и GetLowerBound(1)
равны нулю. Например, если
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
это 2d-массив с 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);
последняя строка предыдущего фрагмента кода вызовет исключение в функции SubArray
расширения в строке
Array.Copy(values, from_index, result, to_index, num_cols);
для row
равного нулю.
Я понимаю, что 2d-массив arr1
(с индексами на основе нуля) размещается в памяти, но не так, как 2d-массив 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 resu<
}
total_cols
является очевидным; что касается from_index
, я не могу найти никакой документации по этому вопросу, но может показаться, что sourceIndex
in Array.Copy
начинает отсчет с sourceArray.GetLowerBound(0)
, а не с нуля, что не обязательно сразу очевидно, учитывая, что этот индекс продолжает расти по строкам и столбцам.
Комментарии:
1. Это действительно работает. Я попытался сделать
SubArray
так, чтобы он не только возвращал массив индексов на основе нуля, как это происходит сейчас, но также (при условии abool rebase
) массив, строки которого начинаются с индексаrow_min
, а столбцы начинаются с индексаcol_min
(путем заменыnew
строки на соответствующуюT[,] result = (T[,]) Array.CreateInstance(typeof(T), new int[] {num_rows, num_cols}, new int[] { rebase ? 0 : row_min, rebase ? 0 : col_min });
). В этом случаеtotal_cols
иfrom_index
не изменяется, ноto_index
делает, и должно быть равноcol_min
, еслиrebase
естьfalse
, но, похоже, это не работает2. @11house
should be equal to col_min
— все наоборот :int to_index = rebase ? 0 : row_min;
. Точно так же, как указано в вопросе, массив. Копирование начинает отсчет сsourceArray.GetLowerBound(0)
, что являетсяrow_min
.