Yunyu L.
Yunyu L.

Reputation: 755

Simplest way to sort coordinates by y-value in Java?

Suppose that I have an (unsorted in any way) array:

[ 12 64 35 ]
[ 95 89 95 ]
[ 32 54 09 ]
[ 87 56 12 ]

I want to sort it so that the second column is in ascending order:

[ 32 54 09 ]
[ 87 56 12 ]
[ 12 64 35 ]
[ 95 89 95 ]

Here are the ways that I thought about dealing with this:

  1. Make each [ x y z ] value into a list, and correlate each xyz value with an identifier, whose property is the y-value of the xyz value. Then, sort the identifiers. (I'm not sure if sorting Java arrays keeps the corresponding values in that row)

  2. Use a hashmap to do the same thing as the previous

However, the above 2 methods are obviously somewhat wasteful and complicated since they rely on an external identifier value which is unneeded, so is there a simpler, faster, and more elegant way to do this?

Sorry if this is a dumb question, I'm not familiar at all with the way that Java sorts arrays.

Upvotes: 5

Views: 1405

Answers (4)

Bohemian
Bohemian

Reputation: 425198

This is a one-liner (if you count an anonymous class as one line), making use of Arrays.sort() and a suitably typed and coded Comparator:

Arrays.sort(grid, new Comparator<int[]>() {
    public int compare(int[] o1, int[] o2) {
        return o1[1] - o2[1];
    }
});

Note the simple comparison expression o1[1] - o2[1] - no need to unbox to Integer and use Integer.compareTo().

Here's a test with your data:

public static void main(String[] args) {
    int[][] grid = new int[][] { 
        { 12, 64, 35 },
        { 95, 89, 95 },
        { 32, 54,  9 },
        { 87, 56, 12 }};
    Arrays.sort(grid, new Comparator<int[]>() {
        public int compare(int[] o1, int[] o2) {
            return o1[1] - o2[1];
        }
    });
    System.out.println(Arrays.deepToString(grid).replace("],", "],\n"));
}

Output:

[[32, 54, 9],
 [87, 56, 12],
 [12, 64, 35],
 [95, 89, 95]]



Just for fun, here it is literally as one line:

Arrays.sort(grid, new Comparator<int[]>() {public int compare(int[] o1, int[] o2) {return o1[1] - o2[1];}});

Upvotes: 6

Mattias Buelens
Mattias Buelens

Reputation: 20179

Use a custom comparator.

This implementation is more generic in that you can use it for any Comparable type and for any sorting index. If you also need a custom comparator for the T type itself, you'll need to pass that in the constructor and replace the .compareTo() call.

public class ArrayElementComparator<T implements Comparable<? super T>> implements Comparator<T[]> {

    private final int sortIndex;

    public ArrayElementComparator(int sortIndex) {
        this.sortIndex = sortIndex;
    }

    @Override
    public int compare(T[] left, T[] right) {
        // Optional: null checks and boundary checks
        if (left == null && right == null) {
            return 0;
        }
        if (left == null || left.length <= sortIndex) {
            return 1;
        }
        if (right == null || right.length <= sortIndex) {
            return -1;
        }
        return left[sortIndex].compareTo(right[sortIndex]);
    }

}

Usage:

List<Integer[]> list = new List<Integer[]>();
// ... Add records
Collections.sort(list, new ArrayElementComparator<Integer>(1));

Upvotes: 2

Deepak Singhal
Deepak Singhal

Reputation: 10876

Easiest and most cleanest way would be to write a small comparator class. That will give you more flexibility in controlling the behavior of sorting also; for example you can sort 1st element or any element of arrays.

Comparator will be something like:

new Comparator(){

            public int compare ( Integer[] obj1, Integer[] obj2)
            {
                return obj1[1].compareTo(obj2[1]); 
            }

Upvotes: 8

Code-Apprentice
Code-Apprentice

Reputation: 83557

If these three values represent (x, y, z) coordinates in a 3D Euclidean space, you could write a class to hold them. Then use a List or array of these points and a customer Comparator to sort them the way you wish.

Upvotes: 1

Related Questions