Вставить после каждого столбца массива, содержащего значение равное нулю столбец из нулей

Размер массива задает пользователь. Преобразование массива выглядит так:

for (int i = 0; i < arr.GetUpperBound(1) + 1; i++)
            {
                for (int j = 0; j < arr.GetUpperBound(0) + 1; j++)
                {
                    if (arr[j, i] == 0)
                    {
                        AddColumn(ref arr, i);
                        i++;
                        break;
                    }
                    dataGridView2.RowCount = (n);
                    dataGridView2.ColumnCount = (m);
                    dataGridView2.Rows[i].Cells[j].Value = arr[i, j];
                }
            }

static void AddColumn(ref int[,] arr, int col)
        {
            int[,] newArr = new int[arr.GetUpperBound(0) + 1, arr.GetUpperBound(1) + 2];
            for (int i = 0; i < newArr.GetUpperBound(0) + 1; i++)
            {
                for (int j = newArr.GetUpperBound(1); j >= 0; j--)
                {
                    if (j > col + 1)
                    {
                        newArr[i, j] = arr[i, j - 1];
                    }
                    else
                    {
                        if (j == col + 1)
                        {
                            newArr[i, j] = 0;
                        }
                        else
                        {
                            newArr[i, j] = arr[i, j];
                        }
                    }

                }
            }
            arr = newArr;
}

При компиляции выдает изначальный массив( Подозреваю что ошибка где то в куске dataGridView2.RowCount = (n); dataGridView2.ColumnCount = (m); DataGridView2.Rows[i].Cells[j].Value = arr[i, j]; но как исправить понять не могу


Ответы (1 шт):

Автор решения: aepot

Не путайтесь в переменных, используйте row, col. При изменении размеров DGV возможна потеря данных, поэтому это не следует делать во время внесения данных, а строго до внесения. Вместо GetUpperBound + 1 можно и нужно использовать GetLength.

Старайтесь избегать использования ref там, где можно без него легко обойтись, используйте возвращаемое значение. Пересоздание массива с полным копированием данных - очень дорогая операция. Ладно когда он у вас 10 на 10, а когда миллион на миллион элементов? Я понимаю, что вы только начинаете, но держите в уме, что копирование данных и выделение памяти под новые объекты - это дополнительные затраты ресурсов процессора.

Поэтому задачу надо разделить на 3 составляющие:

  1. Поиск колонок с нулями
  2. Добавление пустых колонок
  3. Заполнение DataGridView
List<int> zeroCols = new List<int>();

for (int col = 0; col < arr.GetLength(1); col++)
{
    for (int row = 0; row < arr.GetLength(0); row++)
    {
        if (arr[row, col] == 0)
        {
            zeroCols.Add(col);
            break;
        }
    }
}

На этом этапе есть список индексов колонок, после которых надо добавить пустую колонку. А так же, если посчитать количество элементов в этом списке, то известно, насколько шире надо сделать новый массив.

int[,] newArr = new int[arr.GetLength(0), arr.GetLength(1) + zeroCols.Count];
int offset = 0; // при пропуске колонки, надо просто добавить к её индексу смещение
for (int col = 0; col < arr.GetLength(1); col++)
{
    for (int row = 0; row < arr.GetLength(0); row++)
    {
        newArr[row, col + offset] = arr[row, col];
    }
    if (zeroCols.Contains(col))
       offset++;
}

Вот и все решение, осталось только внести в таблицу

dataGridView2.RowCount = newArr.GetLength(0);
dataGridView2.ColumnCount = newArr.GetLength(1); 
for (int row = 0; row < newArr.GetLength(0); row++)
{
    for (int col = 0; col < newArr.GetLength(1); col++)
    {
        dataGridView2.Rows[row].Cells[col].Value = newArr[row, col];
    }
}
→ Ссылка