Транспонирование многомерного массива

У меня есть многомерный массив на основе строк:

/** [row][column]. */
public int[][] tiles;

Я хотел бы преобразовать этот массив в массив на основе столбцов, например:

/** [column][row]. */
public int[][] tiles;

...Но я действительно не знаю, с чего начать


person Antti Kolehmainen    schedule 07.12.2011    source источник


Ответы (8)


попробуй это:

@Test
public void transpose() {
    final int[][] original = new int[][]{
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}};

    for (int i = 0; i < original.length; i++) {
        for (int j = 0; j < original[i].length; j++) {
            System.out.print(original[i][j] + " ");
        }
        System.out.print("\n");
    }
    System.out.print("\n\n matrix transpose:\n");
    // transpose
    if (original.length > 0) {
        for (int i = 0; i < original[0].length; i++) {
            for (int j = 0; j < original.length; j++) {
                System.out.print(original[j][i] + " ");
            }
            System.out.print("\n");
        }
    }
}

выход:

1 2 3 4 
5 6 7 8 
9 10 11 12 


 matrix transpose:
1 5 9 
2 6 10 
3 7 11 
4 8 12 
person Kent    schedule 07.12.2011
comment
Это только распечатывает изменение. На самом деле это не меняет массив. - person Jon Egeland; 08.12.2011
comment
нет, это не изменило массив, просто показав, как работает цикл - person Kent; 08.12.2011

Я видел, что все ответы создают новую результирующую матрицу. Это просто:

matrix[i][j] = matrix[j][i];

Однако вы также можете сделать это на месте, в случае квадратной матрицы.

// Transpose, where m == n
for (int i = 0; i < m; i++) {
    for (int j = i + 1; j < n; j++) {
        int temp = matrix[i][j];
        matrix[i][j] = matrix[j][i];
        matrix[j][i] = temp;
    }
}

Это лучше для больших матриц, где создание новой результирующей матрицы расточительно с точки зрения памяти. Если он не квадратный, вы можете создать новый с размерами NxM и использовать неуместный метод. Примечание: на месте позаботьтесь о j = i + 1. Это не 0.

person Jash Sayani    schedule 13.10.2013
comment
почему это j + 1 вместо 0? Я предполагаю, что это позволяет избежать избыточных шагов, но мой код начал работать после того, как я инициализировал свою переменную j, как вы, вместо 0... кроме того, что у меня был идентичный код - person Alfredo Gallegos; 17.06.2017

Я просто копаю эту тему, потому что не нашел рабочего решения в ответах, поэтому я опубликую его, чтобы помочь всем, кто его ищет:

public int[][] transpose(int[][] array) {
    // empty or unset array, nothing do to here
    if (array == null || array.length == 0)
        return array;

    int width = array.length;
    int height = array[0].length;

    int[][] array_new = new int[height][width];

    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            array_new[y][x] = array[x][y];
        }
    }
    return array_new;
}

вы должны вызвать его, например, через:

int[][] a = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8}};
for (int i = 0; i < a.length; i++) {
    System.out.print("[");
    for (int y = 0; y < a[0].length; y++) {
        System.out.print(a[i][y] + ",");
    }
    System.out.print("]\n");
}

a = transpose(a); // call
System.out.println();

for (int i = 0; i < a.length; i++) {
    System.out.print("[");
    for (int y = 0; y < a[0].length; y++) {
        System.out.print(a[i][y] + ",");
    }
    System.out.print("]\n");
}

который, как и ожидалось, выведет:

[1,2,3,4,]
[5,6,7,8,]

[1,5,]
[2,6,]
[3,7,]
[4,8,]
person luk2302    schedule 13.07.2013

немного более общий способ:

/**
 * Transposes the given array, swapping rows with columns. The given array might contain arrays as elements that are
 * not all of the same length. The returned array will have {@code null} values at those places.
 * 
 * @param <T>
 *            the type of the array
 * 
 * @param array
 *            the array
 * 
 * @return the transposed array
 * 
 * @throws NullPointerException
 *             if the given array is {@code null}
 */
public static <T> T[][] transpose(final T[][] array) {
    Objects.requireNonNull(array);
    // get y count
    final int yCount = Arrays.stream(array).mapToInt(a -> a.length).max().orElse(0);
    final int xCount = array.length;
    final Class<?> componentType = array.getClass().getComponentType().getComponentType();
    @SuppressWarnings("unchecked")
    final T[][] newArray = (T[][]) Array.newInstance(componentType, yCount, xCount);
    for (int x = 0; x < xCount; x++) {
        for (int y = 0; y < yCount; y++) {
            if (array[x] == null || y >= array[x].length) break;
            newArray[y][x] = array[x][y];
        }
    }
    return newArray;
}
person benez    schedule 04.01.2017

Если вы хотите перейти на место транспонирования матрицы (в этом случае row count = col count), вы можете сделать это в Java

public static void inPlaceTranspose(int [][] matrix){

    int rows = matrix.length;
    int cols = matrix[0].length;

    for(int i=0;i<rows;i++){
        for(int j=i+1;j<cols;j++){
            matrix[i][j] = matrix[i][j] + matrix[j][i];
            matrix[j][i] = matrix[i][j] - matrix[j][i];
            matrix[i][j] = matrix[i][j] - matrix[j][i];
        }
    }
}
person Aniket Thakur    schedule 26.01.2014

Используйте эту функцию (при необходимости замените String на int). Он принимает матрицу в виде массива строк и возвращает новую матрицу, которая является транспонированной. Он также проверяет крайний случай пустого массива. Никаких отпечатков.

private String[][] transposeTable(String[][] table) {
    // Transpose of empty table is empty table
    if (table.length < 1) {
        return table;
    }

    // Table isn't empty
    int nRows = table.length;
    int nCols = table[0].length;
    String[][] transpose = new String[nCols][nRows];

    // Do the transpose
    for (int i = 0; i < nRows; i++) {
        for (int j = 0; j < nCols; j++) {
            transpose[j][i] = table[i][j];
        }
    }

    return transpose;
}
person Philomena Lamoureux    schedule 27.11.2019
comment
Пожалуйста, объясните этот код и как он отвечает на вопрос - person Josh; 27.11.2019

Вот мои 50 центов: служебный метод и тест для транспонирования многомерного массива (для двойников в моем случае):

/**
 * Transponse bidimensional array.
 *
 * @param original Original table.
 * @return Transponsed.
 */
public static double[][] transponse(double[][] original) {
    double[][] transponsed = new double
            [original[0].length]
            [original.length];

    for (int i = 0; i < original[0].length; i++) {
        for (int j = 0; j < original.length; j++) {
            transponsed[i][j] = original[j][i];
        }
    }
    return transponsed;
}
@Test
void aMatrix_OfTwoDimensions_ToBeTransponsed() {
    final double[][] original =
            new double[][]{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

    double[][] transponsed = Analysis.transponse(original);

    assertThat(transponsed[1][2], is(equalTo(10)));
}
person Zon    schedule 09.03.2020

public int[][] tiles, temp;

// Add values to tiles, wherever you end up doing that, then:
System.arraycopy(tiles, 0, temp, 0, tiles.length);

for (int row = 0; row < tiles.length; row++) // Loop over rows
    for (int col = 0; col < tiles[row].length; col++) // Loop over columns
        tiles[col][row] = temp[row][col]; // Rotate

Это должно сделать это за вас.

person Jon Egeland    schedule 07.12.2011
comment
Это не сработает. Вы, вероятно, думаете о C или C++; в Java temp = tiles делает tiles и temp ссылками на один и тот же массив, и вы только что полностью испортили его. :-П - person ruakh; 08.12.2011
comment
Что он делает неправильно? Не компилируется? не копировать массив? какие? - person Jon Egeland; 08.12.2011
comment
Ну, это не компилируется - tmp должно быть temp. Кроме того, вы никогда не создаете экземпляр temp (я предполагаю, что tiles поступает из какого-то внешнего источника). Но даже исправив их, он превращает [[1, 2], [3, 4]] в [[1, 2], [2, 4]]. И если матрица прямоугольная, а не квадратная (т. е. N x M вместо N x N), будет выдано исключение ArrayIndexOutOfBoundsException. - person yshavit; 08.12.2011