#c #syntax #multidimensional-array #dimensions
#c #синтаксис #многомерный массив #размеры
Вопрос:
Я написал следующую функцию, чтобы придать объекту двумерного массива нечетные размеры, добавив строку или столбец по мере необходимости (где sizeX, sizeY, get, set и resize являются понятными функциями-членами grid2D).
void makeOdd(grid2D<double> *pSrc)
// ---------------------------------------------------------------------------------------------------------
// Make one or both dimensions of input array odd (via row/column copy).
{
// Variable declarations
grid2D<double> pTmp = *pSrc; // Scratch local source variable
int simax, sjmax; // Source dimensions
// Get source dimensions
sjmax = pSrc->sizeY();
simax = pSrc->sizeX();
// Check if source is already odd-dimensioned
if (sjmax%2 amp;amp; simax%2) return;
// Extend row/column of source if necessary
if (sjmax%2 amp;amp; !(simax%2)) // Odd rows, even columns
{
pSrc->resize(simax 1,sjmax); // Resize source with extra column
for(int i=0; i<simax 1; i )
{
for(int j=0; j<sjmax; j )
{
if(i==simax)
pSrc->set(i,j,pTmp.get(simax-1,j)); // Copy last column
else
pSrc->set(i,j,pTmp.get(i,j));
}
}
return;
}
else if (!(sjmax%2) amp;amp; simax%2) // Even rows, odd columns
{
pSrc->resize(simax,sjmax 1); // Resize source with extra row
for(int i=0; i<simax; i )
{
for(int j=0; j<sjmax 1; j )
{
if(i==simax)
pSrc->set(i,j,pTmp.get(i,sjmax-1)); // Copy last row
else
pSrc->set(i,j,pTmp.get(i,j));
}
}
return;
}
else // Even rows, even columns
{
pSrc->resize(simax 1,sjmax 1); // Resize source with extra row and column
for(int i=0; i<simax 1; i )
{
for(int j=0; j<sjmax 1; j )
{
if(i==simax amp;amp; j==sjmax)
{
pSrc->set(i,j,pTmp.get(simax-1,sjmax-1)); // Copy last column and row
}
else if(i==simax amp;amp; j<sjmax)
{
pSrc->set(i,j,pTmp.get(simax-1,j)); // Copy last column
}
else if(i<simax amp;amp; j==sjmax)
{
pSrc->set(i,j,pTmp.get(i,sjmax-1)); // Copy last row
}
else
{
pSrc->set(i,j,pTmp.get(i,j));
}
}
}
return;
}
}
Мой вопрос: есть ли более чистый / эффективный способ сделать это?
Большое спасибо…
Комментарии:
1. Что именно вы пытаетесь здесь сделать?
2. Например, если у меня есть двойной массив X размером 10×10, я хочу, чтобы X имел размер 11×11, скопировав последнюю строку и столбец, чтобы создать новые размеры.
Ответ №1:
Я думаю, было бы проще сначала проверить количество строк и при необходимости увеличить его на 1. Затем проверьте количество столбцов и при необходимости увеличьте каждый из них на 1.
Предполагая, что ваш grid2d
является оболочкой вокруг vector<vector<T> >
, вы можете передать значение resize
, которое оно будет использовать для заполнения вновь созданного пространства, поэтому, когда вы добавляете строку, вы можете просто передать текущую последнюю строку, чтобы скопировать ее в новую последнюю строку.
Ответ №2:
Ваш код IMO довольно запутан для этой проблемы… Я бы сделал вместо
void makeOdd(grid2D<double> *pSrc)
{
int ny = pSrc->sizeY();
int nx = pSrc->sizeX();
int oddnx = nx (nx % 2 == 0);
int oddny = ny (ny % 2 == 0);
if (nx != oddnx || ny != oddny)
{
pSrc->resize(oddnx, oddny);
if (nx != oddnx)
for (int y=0; y<ny; y )
pSrc->set(nx, y, pSrc->get(nx-1, y));
if (ny != oddny)
for (int x=0; x<oddnx; x )
pSrc->set(x, ny, pSrc->get(x, ny-1));
}
}
Конечно, в зависимости от grid2D
это могло бы быть еще проще, если бы знать внутреннюю структуру объекта вместо использования общедоступного интерфейса resize / get / set (например, путем создания makeOdd
метода).
Кстати, в вашем исходном коде вы создаете копию pTmp
указателя (не исходного объекта); и это тоже бессмысленно.
Комментарии:
1. Привет 6502, Большое спасибо за чистый и сжатый код! Что касается вашего второго пункта, я определил оператор «=» внутри grid2D для сохранения rhs в новый контейнер T (здесь double), чтобы операция не была бессмысленной.
2. Извините, я неправильно прочитал ваш код и подумал, что вы просто делаете копию указателя (и, конечно, вы не можете перегружать назначение указателя). Однако, если операция изменения размера предназначена для сохранения текущего содержимого (как ИМО и должно быть), тогда нет необходимости создавать копию: вы можете просто изменить размер и скопировать элементы из предпоследнего столбца / строки в последний.
3. Привет, 6502, еще раз спасибо за ответ. В моей функции-члене grid2D «resize» я удаляю контейнер <double> и выделяю новый контейнер <double> нового указанного размера. Как вы предлагаете это сделать, чтобы сохранить исходное содержимое?
4. Упс. Я думал, что изменение размера позволяет сохранить содержимое (как и для стандартных контейнеров). Если ваша реализация вместо этого просто удаляет все содержимое, то, по крайней мере, вам следует изменить имя на что-то вроде
recreate
илиzap
. Как написать эффективную операцию изменения размера с сохранением содержимого (IMO очень полезно в целом), конечно, зависит от того, каково внутреннее представление: является ли оно одиночнымstd::vector<T>
с вычисляемым индексом илиstd::vector<std::vector<T> >
? это разреженный массивstd::map<std::pair<int, int>, double>
?5. Контейнерная сетка 2D проста: int grid_size_x, int grid_size_y, int grid_size и T* grid (где T обычно равно <double>). Хранимые данные (некоторые данные дистанционного зондирования) могут быть любыми — от нулевых до полностью заполненных данными, в зависимости от условий. Обязательным требованием является максимально быстрый доступ к данным. Вы предлагаете векторы для этого?