dlawil2049
dlawil2049

Reputation: 61

How to get sub-array of 2d array (matrix)

I'm trying to get a sub matrix of a matrix, but I'm having difficulty with the logic behind it. For a matrix like this:

1 2 3 
4 5 6
7 8 9

I need to be able to get submatrix(A, 3, 2):

1 3 
4 6 

This is what I've tried so far

    public Matrix submatrix(Matrix A, int i, int j) {
    Matrix subM = new Matrix(this.rows + 1, this.columns + 1);
    for (int r = i; r < this.rows; r++) {
        for (int c = j; c < this.columns; c++) {
            subM.data[r - i][c - j] = A.data[r][c];
        }
    }
    return subM;
}

And this is how I'm trying to call it in main

Matrix A = new Matrix(new double[][]{{1, 2, 3},{4, 5, 6},{7, 8, 9}});
    int i = 3;
    int j = 2;
    Matrix m = A.submatrix(A, i, j);
    System.out.println("L:\n" + m);

I'm new to java so I'd appreciate any help.

Upvotes: 2

Views: 1157

Answers (1)

dreamcrash
dreamcrash

Reputation: 51483

You should pass to your method the scope of the sub-matrix you want to copy, namely its starting and ending positions, both regarding the rows and columns, something like:

public Matrix submatrix(Matrix A, int row_begin, int row_end, int col_begin, int col_end) {
    Matrix subM = new Matrix(row_end - row_begin, col_end - col_begin);
    for (int r = row_begin, i=0; r < row_end; r++, i++)
        for (int c = col_begin, j= 0; c < col_end; c++, j++)
            subM.data[i][j] = A.data[r][c];
    return subM;
}

Typically, in problems that you need to simultaneously iterate over two different data structures, and you do not start iterating from the same positions, it is easier to use a different index variable for each of those structures. In the code below, I use the variables i and j to iterate over the matrix subM.data and the variables r and c to iterate over the matrix A.data

Then you would call submatrix(A, 0, 2, 0, 3). The output would be:

1 2 3 
4 5 6

which I think is what you really want, but correct me if I am wrong.

Btw I am assuming a well-behaved input. Normally, you would need to add additional checks on the variables row_begin, row_end, col_begin, col_end to ensure that you will not get into troubles (e.g., IndexOutofbounds).

Now if you really want to be able to skip rows and columns in the middle, then things get more complicated. One solution is to pass as a parameter also the range of columns/rows to be skipped, something like:

     int[][] submatrix(int [][] data, int row_begin, int row_end,
                                    int skip_row_begin, int skip_row_end,
                                    int col_begin, int col_end,
                                    int skip_col_begin, int skip_col_end) {
        int number_rows = row_end - row_begin - (skip_row_end - skip_row_begin);
        int number_cols = col_end - col_begin - (skip_col_end - skip_col_begin);
        int [][] subM = new int[number_rows] [number_cols];
        for (int r = row_begin, i=0; r < row_end; r++) {
            if(r < skip_row_begin || r >= skip_row_end) {
                for (int c = col_begin, j = 0; c < col_end; c++) {
                     if(c < skip_col_begin || c >= skip_col_end) {
                         subM[i][j] = data[r][c];
                         j++;
                     }
                }
                i++;
            }
        }
        return subM;
    }

If you do not want to skip the rows or the columns just give as range the size of the matrix itself. In your example you want to skip the middle columns for that you would call the submatrix method as follows:

int [][] submatrix(data, 0 , 2, data.length, data.length, 0 , 3, 1, 2);

for (int[] ints : a) {
  for (int anInt : ints) 
     System.out.print(anInt + " ");
  System.out.println("\n");
}

This would output:

1 3 
4 6 

Upvotes: 2

Related Questions