1

I've been stumped by this for a while now. I have an array of strings all of which contain some numeric value that I need to extract and use for comparison in order to sort the array. I have tried making use of the built in method sort with a comparator but have not been successful with it.

If anyone could give me a little insight or point me in the right direction that would be greatly appreciated.

The array contains strings in the format: "NAME has worked x hours"

My intent is to pull the number out and sort based off the value of the integer while still keeping the relationship to the name.

public static <T> void sort(T[] a, Comparator<? super T> c)
user2181402
  • 87
  • 2
  • 2
  • 8
  • 1
    can you post the array of string? and the result you want it to be – Rod_Algonquin Sep 04 '14 at 04:45
  • There are tons of answers on implementing "natural sort" in all languages... – Alexei Levenkov Sep 04 '14 at 04:47
  • 1
    possible duplicate of [Natural sort order string comparison in Java - is one built in?](http://stackoverflow.com/questions/1262239/natural-sort-order-string-comparison-in-java-is-one-built-in) – Alexei Levenkov Sep 04 '14 at 04:48
  • @Rod_Algonquin - He has an array of Strings like `{"10","2","1"}`. The problem with natural sorting of Strings (default `Arrays.sort(stringArray)` is that he will get the answer as `{"1","10","2"}`. He needs `{"1","2","10"}` (integer sort). – TheLostMind Sep 04 '14 at 04:50
  • 1
    @TheLostMind - I agree, I think this is the problem. However, I think the answer is to _parse the strings_ into custom objects, and then sort those instead. I can't think of any benefit to dealing directly with Strings, especially if your objects have an equivalent toString method. – DaoWen Sep 04 '14 at 04:53
  • Clarified in the edit – user2181402 Sep 04 '14 at 04:53
  • @DaoWen - Yes. I agree with your point. The OP has to Parse the String into a valid integer representation – TheLostMind Sep 04 '14 at 04:55

3 Answers3

2

You can use the Collections.sort to sort your string using the comparator and parsing the String to Integer to enable you to sort it by integer.

sample:

    String s[] = { "10", "2", "1" };
    Collections.sort(Arrays.asList(s), new Comparator<String>() {

        @Override
        public int compare(String o1, String o2) {
            int i = Integer.parseInt(o1);
            int i2 = Integer.parseInt(o2);
            if (i > i2)
                return 1;
            else if (i < i2)
                return -1;
            else
                return 0;
        }
    });
    System.out.println(Arrays.toString(s));

result:

[1, 2, 10]
Rod_Algonquin
  • 26,074
  • 6
  • 52
  • 63
  • *The array contains strings in the format: "NAME has worked x hours"* - So, he needs to change his `compare()` logic somewhat (based on the edited question). But more or less, this is the correct answer. +1. – TheLostMind Sep 04 '14 at 04:57
2

Make sure you handle all the edge cases but the below code should work for you.

public class NumericStringComparator implements Comparator<String> {
    @Override
    public int compare(String str1, String str2) {
        Integer num1 = extractNumericValue(str1);
        Integer num2 = extractNumericValue(str2);

        // handle null/error cases

        return num1.compareTo(num2);
    }

    private static Integer extractNumericValue(String str) {
        // extract numeric value however but as an example
        return Integer.parseInt(str);
    }
}

With this comparator you can use the Arrays.sort(..) method to sort your list

String[] array = ...;
Arrays.sort(array, new NumericStringComparator());
Upio
  • 1,364
  • 1
  • 12
  • 27
  • 3
    Best of many answers IMHO. BTW, if `extractNumericValue()` returned an `Integer`, the whole comparison part would shrink to `extractValue(str1).compareTo(extractValue(str2))` – Jan Groth Sep 04 '14 at 05:35
0

if each string only contains numbers, then you can just use ParseInt to get integer values for each string and then sort them using a regular comparator. If the strings contain non-numeric characters and integers, then this complicates things, and you might want to make a helper method to do the dirty work for you. A possible (though inefficient) implementation might look like...

public static int getNumbersFromString(String string)
{
    String numbers = "";
    for(int i = 0; i < string.length; i++)
    {
        if((int)(string.charAt(i) >= 48 && (int)(string.charAt(i) <= 57)
            numbers += string.charAt(i);
    }
    int foo = Integer.parseInt(numbers);
    return foo;
} 
Kevin
  • 302
  • 2
  • 11