Rookie
Rookie

Reputation: 351

How to sort an array of strings (in the form of names concatenated with numbers) in Java?

In case, I have an array of strings in the following format -

["synthia 16", "alicia 3", "alicia 2", "alicia 1", "synthia 2"]

The list is to be sorted by name first and then the following number. The output of sorting should be-

["alicia 1", "alicia 2", "alicia 3", "synthia 2", "synthia 16"]

I used comaparator to do this using Java:

import java.util.Comparator;
import java.util.Arrays;

public class SortList {

public static void main ( String[] args) {
    String[] names = {"synthia 16", "alicia 4", "alicia 19", "alicia 1", "synthia 2"};
    System.out.println("Unsorted list:\n ");        
    displayList(names);

    Arrays.sort(names, new nameComparator());
    System.out.println("\nSorted list:\n");
    displayList(names);
}

public static void displayList(String[] names) {
    for(String name:names) {
        System.out.println(name);
    }
}

private static class nameComparator implements Comparator<String> {
    @Override
    public int compare(String s1, String s2) {
        String[] s1NameNumPair = s1.split(" ");
        String[] s2NameNumPair = s2.split(" ");
        if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) > 1) {
            return 1;
        } else if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) < 1) {
            return -1;
        } else {
            Double n1 = Double.parseDouble(s1NameNumPair[1]);
            Double n2 = Double.parseDouble(s2NameNumPair[1]);
            if (n1 > n2) { return 1; }
            else if (n1 < n2) { return -1; }
            else { return 0; }                
        }
    }
}
}

However, using comparator like this only sorts the array alphabetically by the name. Here's the output this code generates:

Unsorted list:

synthia 16
alicia 4
alicia 19
alicia 1
synthia 2

Sorted list:

alicia 1
alicia 19
alicia 4
synthia 2
synthia 16

How can I get the right sorted output?

Upvotes: 2

Views: 217

Answers (4)

heelha
heelha

Reputation: 76

You can use a comparator like this :

  1. Java 7

    Comparator<String> comparator = new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        String[] strings1 = o1.split("\\s+");
        String[] strings2 = o2.split("\\s+");
        int firstCompare = strings1[0].compareTo(strings2[0]);
        int secondCompare = Integer.valueOf(strings1[1]).compareTo(Integer.valueOf(strings2[1]));
    
        return firstCompare*2 + secondCompare;
    }
    

    };

  2. Java 8

    Comparator<String> comparator =
    (String o1, String o2)-> {
        String[] strings1 = o1.split("\\s+");
        String[] strings2 = o2.split("\\s+");
        int firstCompare = strings1[0].compareTo(strings2[0]);
        int secondCompare = Integer.valueOf(strings1[1]).compareTo(Integer.valueOf(strings2[1]));
    
        return firstCompare*2 + secondCompare;
    };
    

Upvotes: 1

Noushad
Noushad

Reputation: 532

Please change the comparison as below.

private static class nameComparator implements Comparator<String> {
    @Override
    public int compare(String s1, String s2) {
        String[] s1NameNumPair = s1.split(" ");
        String[] s2NameNumPair = s2.split(" ");
        if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) > 1) {
            return 1;
        } else if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) < 0) { //here it should be <0 not <1
            return -1;
        } else {
            Double n1 = Double.parseDouble(s1NameNumPair[1]);
            Double n2 = Double.parseDouble(s2NameNumPair[1]);
            if (n1 > n2) {
                return 1;
            } else if (n1 < n2) {
                return -1;
            } else {
                return 0;
            }
        }
    }
}

Upvotes: 1

Sagar
Sagar

Reputation: 838

You must check for > 0 and < 0 so that == 0 will go to else, try below

if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) > 0) {
    return 1;
} else if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) < 0) {
    return -1;
} else {
    Double n1 = Double.parseDouble(s1NameNumPair[1]);
    Double n2 = Double.parseDouble(s2NameNumPair[1]);
    return n1.compareTo(n2);
}

Upvotes: 4

Jessie Brian Revil
Jessie Brian Revil

Reputation: 466

Change your nameComparator to this:

private static class nameComparator implements Comparator<String> {
    @Override
    public int compare(String s1, String s2) {
        String[] s1NameNumPair = s1.split(" ");
        String[] s2NameNumPair = s2.split(" ");
        int diff = s1NameNumPair[0].compareTo(s2NameNumPair[0]);

        if (0 == diff) {
            Double n1 = Double.parseDouble(s1NameNumPair[1]);
            Double n2 = Double.parseDouble(s2NameNumPair[1]);

            return n1.compareTo(n2);
        }

        return diff;
    }
}

Upvotes: 2

Related Questions