Умножение 2d-массива целиком c#

#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