0

I am trying to sort a 2D array based on the column and values but never got the result back as i want.

public class SortColl {
public static void main(String args[]){
 String[][] multi = new String [][]{
                    {"Josef", "cool"},
                    {"Josef", "bat"},
                    {"zeta", "doen"},
                    {"zeta", "up"},
                    {"root", "local"},
                    {"root", "region"}
     };

Arrays.sort(multi, new Comparator<String[]>(){
    @Override
    public int compare(String[] first, String[] second){
         final String time1 = first[0];
         final String time2 = second[0];
        return time1.compareTo(time2);
    }

});

for (int i=0; i< multi.length; i++){
    String[] row = multi[i];
    for(int j=0; j<row.length;j++){
        System.out.println(" , " + row[j] );
    }

}
}

}

For the above, I want to get the result as

{"Josef", "bat"},
{"Josef", "cool"},
{"root", "local"},
{"root", "region"}                  
{"zeta", "doen"},                   
{"zeta", "up"}, 

Can any one please guide me?

4
  • Seperate each dimension into 1d array and use .sort() onn it Commented Mar 15, 2017 at 15:17
  • 2
    You currently only care about the first item in that sub-array and now you say you also want to care about the second item if the first one is equal ... shouldn't the way to implement this be obivous? Commented Mar 15, 2017 at 15:17
  • 3
    compare first[0] with second[0]. if the result is not 0, return the result of the comparation. But, if the result is 0, compare first[1] with second[1] and return the result of the other comparation Commented Mar 15, 2017 at 15:18
  • 2
    You need to understand how those "2D arrays" are being represented in memory first. Then you see the error quickly. Commented Mar 15, 2017 at 15:18

5 Answers 5

4

You can use the Comparator function, but you have to comprehend how a 2D array is represented in the memory.

String[][] multi = new String [][]{
    {"Josef", "cool"},
    {"Josef", "bat"},
    {"zeta", "doen"}
};

This means that multi is an array of array. The first index of multi is an array with contents "Josef" and "cool". The second "Josef" and "bat". And so on.

More visually:

multi ----> [ ][ ][ ]
             |  |  |
             |  |  \->["zeta", "doen"]
             |  |
             |  \-> ["Josef"]["bat"]
             |
             \-> ["Josef"]["cool"]

When using the Array.sort(), the comparator receives a 1D array as arguments. So when the arguments are String[] first, String[] second then in memory, you have (when the Array.sort() function is doing the first step)

first --> ["Josef"]["cool"]
second--> ["Josef"]["bat"]

So, in order to sort correctly, you have to check the first element. If it matches, then check the second element. Hence I've adapted your comparator class;

Arrays.sort(multi, new Comparator<String[]>(){
    @Override
    public int compare(String[] first, String[] second){
        // compare the first element
        int comparedTo = first[0].compareTo(second[0]);
        // if the first element is same (result is 0), compare the second element
        if (comparedTo == 0) return first[1].compareTo(second[1]);
        else return comparedTo;
    }
});

This should do the job.

Sign up to request clarification or add additional context in comments.

Comments

1

Modify your sorting mechanism somewhat like

   Arrays.sort(multi, new Comparator<String[]>(){
            @Override
            public int compare(String[] first, String[] second){
                final String time1 = first[0];
                final String time2 = second[0];
                int compare = time1.compareTo(time2);
                if(compare != 0){
                    return compare;
                }else{
                    return first[1].compareTo(second[1]);
                }
            }

        });

You can also write it as in java 8

Arrays.sort(multi, (first, second) -> {
    final String time1 = first[0];
    final String time2 = second[0];
    int compare = time1.compareTo(time2);
    if(compare != 0){
        return compare;
    }else{
        return first[1].compareTo(second[1]);
    }
})

Comments

1

Appreciate this is an old post, so if anyone is coming across this in future:

Arrays.sort(multi, (a,b) -> a[0].compareTo(b[0]));

1 Comment

This is the answer!
0

The only way I can see of doing this is to separate out into left and right columns, sort those and then rejoin.

 String[][] multi = new String [][]{
     {"Josef", "cool"},
     {"Josef", "bat"},
     {"zeta", "doen"},
     {"zeta", "up"},
     {"root", "local"},
     {"root", "region"}
 };

 String [] left = new String[multi.length]; 
 for (int i = 0; i < multi.length; i++) {
     left[i] = multi[i][0];
 }
 Arrays.sort(left);

 String [] right = new String[multi.length]; 
 for (int i = 0; i < multi.length; i++) {
     right[i] = multi[i][1];
 }
 Arrays.sort(right);

 for (int i = 0; i < multi.length; i++) {
     multi[i][0] = left[i];
     multi[i][1] = right[i];
 }

4 Comments

He does not want to sort both columns independently, what he wants is a sorting by multiple criteria (first by the first column and later by the second column).
Well now is the question how one interprets OPs question. Your answer disconnects "left" and "right", but one can also keep the connection and re-sort "right" if "left" is equal. I wonder what OP really want.
@Tom Yeah, I think I might have misunderstood, will leave answer up until originator comments
That answer doesn't hurt, but I would enhance it to show the differencing results of your approach. (i.e. having a starting array ilke {"Josef", "up"}, {"Josef", "region"}, {"zeta", "local"}, {"zeta", "cool"}, {"root", "doen"}, {"root", "bat"} with different values in the "right" column), so OP (and others) can see that your approach would produce a different result than for example KarelGs approach.
0

If you are using Java 8 then you can create an element comparator and use that in your sort:

private Comparator<String[]> byElement(int i) {
    return Comparator.comparing(a -> a[i]);
}

Arrays.sort(multi, byElement(0).thenComparing(byElement(1)));

Personally I find this a more elegant representation than implementing your own compareTo method. It also makes it trivial to add new elements to the comparison, or reverse one field, or handle nulls first or last etc. with standard Comparator methods rather than custom code.

6 Comments

Can we sort 2d array directly like this?
@minigeek depends on what you mean. And no, this answer can't be used for any kind of 2D array.
@Tom could you explain your comment further? As far as I'm aware this works for all kinds of 2D arrays.
@sprinter It would work, yes, but it wouldn't consider other columns than the first two. For example if you have a 3x3 array. Your code sorts for the first two columns, but the third column can appear "unordered" if the values of the first two columns are equal.
@Tom Ok so 'can't be used for any kind of 2D array' means 'won't automatically sort by unlimited numbers of elements'. Got it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.