3

I have for example this multidimensional array:

String[][] array = new String[10][2];

In the first column I have strings which are in my case usernames, but in the second column I have strings which should represent integers. Now I want to sort the array like this:

Before:

Petter 543
John   276
Jay    1879
Alf    5021
etc.

After:

Alf    5021
Jay    1879
Petter 543
John   276
etc.

So I want the highest value at the top and the lowest at the bottom but don't mess up the names. All I found till now is how to sort bother all integer multidimensional arrays or only string multidimensional arrays and not how to just sort the second column based on just integers.

I once got it sorted but it was sorted in "alphabetic" way:

So 1000 was the highest score 12 was the second highest score and 999999 was the lowest score.

Like 1 represents "a" and 9 represents "z".

0

6 Answers 6

4

Using Java 8 streams:

String[][] out = Arrays.stream(names)
    .sorted(Comparator.comparing(x -> -Integer.parseInt(x[1])))
    .toArray(String[][]::new);
Sign up to request clarification or add additional context in comments.

Comments

3

If the person and the id are associated in some way, then it would be better to create a class that models them (POJO), make that POJO class comparable, define a list of the POJO and use Collections#sort to sorted according to the desired criteria...

another thing to consider is that you have a 2 dimentional String array String[][] but your question states

...How to sort multidimensional string array by one column in integer value in java?

which means that you need to consider to parse the string to integer... (just as a nice hint)

public class MyPojo implement Comparator<MyPojo>{

private String name;

private String id;
...implements the method of the comparator 

}

the do in the main test class

List<MyPojo> mList = new ArrayList<MyPojo>();
mList.add(...);
mList.add(...);
mList.add(...);



Collections.sort(mList);
System.out.println(mList)

1 Comment

I will take a look at that one!
2

Loop over the array until its sorted and swap each time it's not.

public static void main(String[] args) {
    String[][] array = new String[4][2];
    array[0][0] = "Petter"; array[0][1] = "543";
    array[1][0] = "John";   array[1][1] = "276";
    array[2][0] = "Jay";    array[2][1] = "1879";
    array[3][0] = "Alf";    array[3][1] = "5021";

    System.out.println(Arrays.deepToString(array)); // [[Petter, 543], [John, 276], [Jay, 1879], [Alf, 5021]]

    sortArrayByScore(array);

    System.out.println(Arrays.deepToString(array)); // [[Alf, 5021], [Jay, 1879], [Petter, 543], [John, 276]]
}

public static void sortArrayByScore(String[][] array) {
    String tmpName, tmpScore;
    boolean sorted = false;

    while (!sorted) {
        sorted = true;
        for (int i = 0 ; i < array.length - 1 ; i++) {
            if (Integer.parseInt(array[i][1]) < Integer.parseInt(array[i+1][1])){
                sorted = false;
                // SWAP NAMES
                tmpName = array[i][0];
                array[i][0] = array[i+1][0];
                array[i+1][0] = tmpName;

                // SWAP SCORES
                tmpScore = array[i][1];
                array[i][1] = array[i+1][1];
                array[i+1][1] = tmpScore;
            }
        }
    }

}

1 Comment

I will defenitly take a look at that when I have time to do but for now krzyk's answer is really good!
2

My advice would be to take the second column of the 2D array, and put it in its own integer array. Then, call Arrays.sort() on that array. Finally, place the newly sorted array back into the 2D array as string values. Here is what it should look like,

int arr = new int[10];
String[][] copy = new String[10][2];
for(int i = 0; i < array.length; i++){
    arr[i] = Integer.parseInt(array[i][1]);
    System.arraycopy(array[i], 0, copy[i], 0, array[i].length);
}
Arrays.sort(arr);
for(int i = 0; i < array.length; i++){
    array[i][1] = String.valueOf(arr[i]);
}

//fixing the names
for(int i = 0; i < copy.length; i++){
    for(int j = 0; j < array.length; j++){
        if(copy[i][1] == array[j][1]){
             array[j][0] = copy[i][0];
             break;
        }
    }
}

EDIT: To address the order of the names, I changed the code to include a copy of the 2D array so that after rewriting the integer values in order, a check is done to see where each integer moved. For each integer, the corresponding name is transferred to where the integer moved.

2 Comments

Yes, but now the names are screwed up and Alf has a score of 120 if he had before one of 5000 which I don't want.
@creativecreatorormaybenot i see, my mistake. To address the name issue, I thought of making a copy of the 2D array so that after sorting the int values, you can go back and fix the names accordingly by seeing where the int values changed places. This way, you can reassign the name to where its corresponding int value changed to.
1

Use a comparator to sort the items in an array. In your case you have an array of arrays so you need a comparator for an array. You can use a Comparator of String array which assumes the 2nd item is the value.

public class SomeComparator implements Comparator<String[]> {
    /**
     * Assumes each row is length 2 and the 2nd String is really a number.
     */
    @Override
    public int compare(String[] row1, String[] row2) {
        int value1 = Integer.parseInt(row1[1]);
        int value2 = Integer.parseInt(row2[1]);
        // compare value2 first to sort descending (high to low)
        return Integer.compare(value2, value1);
    }
}

Then you can sort using Arrays.sort like this

String[][] data = newData(); // or however you get your data
Arrays.sort(data, new SomeComparator());

4 Comments

Using a Comparator is correct, but stylistically it might be nicer to either inline the comparator definition using lambdas, or take the OO route and define a Comparable POJO to store the data as another commenter has suggested.
Hi @IgnatiusNothnagel - I prefer to extract the code to a helper method or class for reuse and testing. Copying the data into a POJO, sorting, and copying back would work but seems like unnecessary work as the data can be sorted in place.
That makes sense, especially with regards to testing.
@IgnatiusNothnagel the inline lamda is nice but I suggest using Integer.compareTo to avoid problems with integer values greater than half MAX_VALUE and less than half MIN_VALUE. Arrays.sort(data, (o1, o2) -> Integer.valueOf(o2[1]).compareTo(Integer.valueOf(o1[1])));
1

You can use a Comparator that sorts the inner String[] items on the Integer value of the second element, instead of using the default string sort:

Arrays.sort(array, (o1, o2) -> Integer.valueOf(o2[1]).compareTo(Integer.valueOf(o1[1])));

Here you are using lambda syntax to do the same as would be achieved by:

Arrays.sort(data, new Comparator<String[]>() {
    @Override
    public int compare(String[] o1, String[] o2) {
        return Integer.valueOf(o2[1]).compareTo(Integer.valueOf(o1[1]));
    }
});

2 Comments

To elaborate: While what I've written above would work, I think it is more elegant to define a Comparable POJO to store the data, as another commenter has suggested, unless you have good performance or other reasons not to do so.
That is what I was intentional searching for!

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.