Home > Software design >  how to sort two dimensional array by one column in Java
how to sort two dimensional array by one column in Java

Time:10-22

So what I want is this

int[][] arr=new int[2][8];

input:

1 1 3 1 5 3 7 1

5 2 4 8 3 7 5 2

output:

1 1 5 3 1 7 3 1

2 2 3 4 5 5 7 8

you can see that it is sorted by the second row in ascending order and the first row just follows, how can I do this? help, please.

I tried doing below

Arrays.sort(arr[1]);

but I don't think it is working. It does sort the second row in ascending order but the first row is not matching the initial pair with the second row

CodePudding user response:

Try this.

public static void main(String[] args) {
    int[][] array = {
        {1, 1, 3, 1, 5, 3, 7, 1},
        {5, 2, 4, 8, 3, 7, 5, 2}
    };

    List<int[]> list = new AbstractList<int[]>() {

        @Override
        public int[] get(int index) {
            return new int[] {array[1][index], array[0][index]};
        }

        @Override
        public int[] set(int index, int[] value) {
            int[] old = get(index);
            array[1][index] = value[0];
            array[0][index] = value[1];
            return old;
        }

        @Override
        public int size() {
            return array[0].length;
        }
    };

    Collections.sort(list, Arrays::compare);

    for (int[] row : array)
        System.out.println(Arrays.toString(row));
}

output:

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

Or

public static void main(String[] args) {
    int[][] array = {
        {1, 1, 3, 1, 5, 3, 7, 1},
        {5, 2, 4, 8, 3, 7, 5, 2}
    };

    int[] sortedIndexes = IntStream.range(0, array[0].length)
        .boxed()
        .sorted(Comparator.comparing((Integer i) -> array[1][i])
            .thenComparing(i -> array[0][i]))
        .mapToInt(Integer::intValue)
        .toArray();

    int[][] output = IntStream.range(0, array.length)
        .mapToObj(r -> IntStream.range(0, array[r].length)
            .map(i -> array[r][sortedIndexes[i]])
            .toArray())
        .toArray(int[][]::new);

    for (int[] r : output)
        System.out.println(Arrays.toString(r));
}

CodePudding user response:

It may be implemented using helper method(s) to transpose the input array, then transposed array may be sorted by column, and transposed again to restore the original rows/cols:

// create new array to store transposed
public static int[][] transpose(int[][] src) {
    return transpose(src, new int[src[0].length][src.length]);
}    

// use existing array to store the transposed
public static int[][] transpose(int[][] src, int[][] dst) {
    for (int i = 0, n = src.length; i < n; i  ) {
        for (int j = 0, m = src[i].length; j < m; j  ) {
            dst[j][i] = src[i][j];
        }
    }
    return dst;
}

Method sortByColumn (reusing the input array):

public static void sortByColumn(int[][] arr, Comparator<int[]> comparator) {
    int[][] toSort = transpose(arr);
    Arrays.sort(toSort, comparator);
    transpose(toSort, arr);
}

Test:

int[][] arr = {
    {7, 1, 3, 1, 5, 3, 1, 4, 4},
    {5, 2, 4, 8, 3, 7, 5, 2, 5}
};

sortByColumn(arr, Comparator.comparingInt(col -> col[1]));

for (int[] row : arr) {
    System.out.println(Arrays.toString(row));
}

Output: in the first row values appear in the insertion order after sorting by the second element in each column.

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

Square arrays (width == height) may be transposed more efficiently without creating additional array:

public static int[][] transposeSquare(int[][] arr) {
    for (int i = 0, n = arr.length; i < n; i  ) {
        // select the elements only above the main diagonal
        for (int j = i   1, m = arr[i].length; j < m; j  ) {
            int tmp = arr[i][j];
            arr[i][j] = arr[j][i];
            arr[j][i] = tmp;
        }
    }
    return arr;
}
  • Related