rakeeee
rakeeee

Reputation: 1073

Sort 2D String array in java

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?

Upvotes: 0

Views: 4065

Answers (5)

Dono
Dono

Reputation: 11

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]));

Upvotes: 1

sprinter
sprinter

Reputation: 27946

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.

Upvotes: 0

Dhruv Pal
Dhruv Pal

Reputation: 957

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]);
    }
})

Upvotes: 1

KarelG
KarelG

Reputation: 5234

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.

Upvotes: 4

Adam
Adam

Reputation: 36703

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];
 }

Upvotes: 0

Related Questions