Вырезать строки матрицы без использования петель - PullRequest
1 голос
/ 18 августа 2010

У меня есть матрица, и я хочу создать новую матрицу, которая будет старой матрицей, но без первой строки и первого столбца. Есть ли способ сделать это без использования циклов?

Ответы [ 4 ]

1 голос
/ 18 августа 2010

я хочу создать новую матрицу

Из этого мне кажется, что вы хотите новый T[,] объект.

, который будетстарая матрица, но без первой строки и первого столбца

Я понимаю, что вы хотите, чтобы новый T[,] объект содержал те же значения , что и исходный, за исключениемпервая строка / столбец.

есть ли способ сделать это без использования циклов?

Если я правильно истолковал ваш вопрос, то нет, не совсем.Вам нужно будет скопировать элементы из одного массива в другой;это требует перечисления.Но это не значит, что вы не можете абстрагировать реализацию этого метода в метод многократного использования (на самом деле это то, что вы должны делать).

public static T[,] SubMatrix(this T[,] matrix, int xstart, int ystart)
{
    int width = matrix.GetLength(0);
    int height = matrix.GetLength(1);

    if (xstart < 0 || xstart >= width)
    {
        throw new ArgumentOutOfRangeException("xstart");
    }
    else if (ystart < 0 || ystart >= height)
    {
        throw new ArgumentOutOfRangeException("ystart");
    }

    T[,] submatrix = new T[width - xstart, height - ystart];

    for (int i = xstart; i < width; ++i)
    {
        for (int j = ystart; j < height; ++j)
        {
            submatrix[i - xstart, j - ystart] = matrix[i, j];
        }
    }

    return submatrix;
}

Приведенный выше кодэто не красиво, но как только оно будет на месте, вы сможете использовать его довольно аккуратно:

T[,] withoutFirstRowAndColumn = originalMatrix.SubMatrix(1, 1);

Теперь, если я неверно истолковал ваш вопрос, и вы не умерли ...настроив на создание нового объекта T[,], вы можете повысить эффективность этого подхода, вообще не выделяя новый T[,];Вы можете взять идею Абеля (вместе с ее предостережениями) и использовать код unsafe, чтобы по существу моделировать a T[,] с индексами, указывающими на элементы исходной матрицы.Если подумать, вы могли бы даже достичь этого, не прибегая к коду unsafe;вам просто нужно определить интерфейс для функциональности, которую вы хотели бы предоставить (свойство this[int, int] приходит на ум), а затем реализовать эту функциональность (в этом случае тип возвращаемого значения не будет T[,], ноя понимаю, что это может быть что-то вроде это).

0 голосов
/ 19 сентября 2017

Используя некоторые методы из класса Buffer , вы можете сделать построчное копирование, если тип элемента матрицы является примитивным типом. Это должно быть быстрее, чем поэлементная копия. Вот общий метод расширения, который демонстрирует использование буфера:

static PrimitiveType[,] SubMatrix<PrimitiveType>(
    this PrimitiveType[,] matrix, int fromRow, int fromCol) where PrimitiveType: struct
{
    var (srcRowCount, srcColCount) = ( matrix.GetLength(0), matrix.GetLength(1) );
    if (fromRow < 0 || fromRow > srcRowCount)
    {
        throw new IndexOutOfRangeException(nameof(fromRow));
    }
    if (fromCol < 0 || fromCol > srcColCount)
    {
        throw new IndexOutOfRangeException(nameof(fromCol));
    }            
    var (dstRowCount, dstColCount) = ( srcRowCount - fromRow, srcColCount - fromCol );
    var subMatrix = new PrimitiveType[dstRowCount, dstColCount];
    var elementSize = Buffer.ByteLength(matrix) / matrix.Length;
    for (var row = 0; row < dstRowCount; ++row)
    {
        var srcOffset = (srcColCount * (row + fromRow) + fromCol) * elementSize;
        var dstOffset = dstColCount * row * elementSize;
        Buffer.BlockCopy(matrix, srcOffset, subMatrix, dstOffset, dstColCount * elementSize);
    }
    return subMatrix;
}
0 голосов
/ 18 августа 2010

Может быть, вам стоит взглянуть на использование математической библиотеки с хорошей поддержкой операций Matrix?Вот поток, в котором упоминается несколько:

Матричная библиотека для .NET

0 голосов
/ 18 августа 2010

Проще говоря: нет.Но если вы не используете зубчатые массивы, а вместо этого используете многомерные массивы, и если вы потратите некоторое время на изучение структуры памяти массивов в .NET, вы можете сделать это с помощью небезопасных указателей и удаления части памяти и перемещенияначальный указатель многомерного массива.Но это все равно будет зависеть от того, как вы спроектируете свои массивы и свои матрицы, будет ли это работать или нет.

Однако я бы настоятельно посоветовал против этого.Если вы это сделаете, есть большая вероятность, что вы испортите тип и перепутаете сборщик мусора.

В качестве альтернативы, если вы хотите выполнить это упражнение, используйте C ++ / CLI для этой задачи.В C ++ у вас больше контроля, и вам легче манипулировать памятью и перемещать указатели напрямую.У вас также есть больший контроль над деструктором и финализаторами, которые могут пригодиться здесь.Но, тем не менее, тогда вам все еще нужно маршалинг.Если вы сделаете все это для повышения производительности, я бы посоветовал вернуться к простым циклам, в большинстве случаев он будет работать быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...