#c#
#c#
Вопрос:
Я пытаюсь создать 2d-массив, который удваивает другой 2d-массив. Например, если бы у меня был массив с высотой 2 и шириной 2, новый массив имел бы в два раза больше. То же самое касается его содержимого: если исходный массив состоял из 1,0,2,0
, я бы хотел, чтобы новый массив состоял из 1,1,0,0,2,2,0,0
.
Кто-нибудь знает, как это сделать, или если это возможно?
int height = 2;
int width = 2;
int[,] arr1 = new int[height,width];
arr1[0,0] = 0;
arr1[0, 1] = 2;
arr1[1, 0] = 1;
arr1[1, 1] = 0;
int newheight = height * 2;
int newwidth = width * 2;
int[,] newarr = new int[newheight, newwidth];
Комментарии:
1. » если бы у меня был массив с высотой 2 и шириной два, у нового массива было бы вдвое больше. » -> удвоить количество чего? ширина ? высота? оба? Пример «1,0,2,0» —> «1,1,0,0,2,2,0,0», похоже, предполагает, что это либо высота, либо ширина, но не оба, тогда как то, что вы закодировали, подразумевает, что это и то, и другое. Итак, в вашем описании есть противоречие.
2. похоже, у вас уже есть код для создания массива в двойном размере. Я не думаю, что есть лучший способ для копирования данных, чем два
for
цикла.3. Если ответ Яна верен, вы в основном выполняете «интерполяцию ближайшего соседа».
Ответ №1:
Итак, если ваш оригинал выглядит как:
0 2
1 0
И вы хотите, чтобы ваш новый массив выглядел так?
0 0 2 2
0 0 2 2
1 1 0 0
1 1 0 0
Конечно, тогда просто используйте каждое значение дважды:
int[,] newarr = new int[newheight, newwidth];
for(int i=0;i<newheight;i )
{
for(int j=0;j<newwidth;j )
{
// Divide index by 2 to ensure we don't overflow original array
newarr[i,j] = arr[i/2, j/2];
}
}
Ответ №2:
Ответ Ians в порядке, не считая использования синтаксиса неровного массива в многомерном массиве (сейчас исправлено).
В академических целях я попытался быстро собрать решение, которое могло бы работать с любым размером и любым измерением.
К сожалению, для этого нет общего ограничения System.Array
, поэтому нам приходится жить с приведением (где-то). Кроме того, его, вероятно, можно было бы сделать немного более эффективным.
Учитывая
public static Array Inflate<T>(Array source, int size)
{
// get the lengths of each dimension multiplied by the inflation size
var lengths = Enumerable
.Range(0, source.Rank)
.Select(x => source.GetLength(x) * size)
.ToArray();
var indices = new int[source.Rank]; // this is the index map of what we want to set
var originals = new int[source.Rank]; // this is the index map of the array to interpolate from
// this is how we create an array of with arbitrary dimensions
var instance = Array.CreateInstance(typeof(T), lengths);
do
{
// GetValue and SetValue takes an index map
instance.SetValue(source.GetValue(originals), indices);
// this increments each element in the dimension
// when it hits the last element, goes to the next dimension
// and increments that, setting the last to 0
// you can think of it like an minutes, hour, day, type clock
for (var i = 0; i < lengths.Length; i )
{
indices[i] ;
originals[i] = indices[i] / size; // original index
if (indices[i] < lengths[i])
break;
indices[i] = originals[i] = 0;
}
// if we are back to 0, we have finished
} while (indices.Any(x => x != 0));
return instance;
}
Тестовые данные
var arr1 = new int[2, 2, 2];
arr1[0, 0, 0] = 0;
arr1[1, 0, 0] = 1;
arr1[0, 1, 0] = 2;
arr1[1, 1, 0] = 3;
arr1[0, 0, 1] = 4;
arr1[1, 0, 1] = 5;
arr1[0, 1, 1] = 6;
arr1[1, 1, 1] = 7;
Использование
// inflate a 3 dimensional array by 2 in each dimension
var result = (int[,,])Inflate<int>(arr1, 2);
Печать результатов
Предупреждение: это головоломка, поскольку концептуально мы пытаемся напечатать третье измерение на 2-мерной консоли. Итак, я в основном просто сокращаю 3-е измерение (z)
for (var z = 0; z < result.GetLength(2); z )
{
Console.WriteLine($"z = {z}");
for (int x = 0; x < result.GetLength(0); x )
{
for (int y = 0; y < result.GetLength(1); y )
{
Console.Write(result[x,y,z] " ");
}
Console.WriteLine();
}
}
Вывод
z = 0
0 0 2 2
0 0 2 2
1 1 3 3
1 1 3 3
z = 1
0 0 2 2
0 0 2 2
1 1 3 3
1 1 3 3
z = 2
4 4 6 6
4 4 6 6
5 5 7 7
5 5 7 7
z = 3
4 4 6 6
4 4 6 6
5 5 7 7
5 5 7 7