-4

I want to sort alpha-numeric values as if my input is

[a1, b1, c1, aa1, bb1, cc1, d1, e1]

Output should be in this order- a1,b1,c1,d1,e1,aa1,bb1,cc1

I have used this code

public class coll {

    public static int comparator(String s1, String s2) {

        String[] pt1 = s1.split("((?<=[a-z])(?=[0-9]))|((?<=[0-9])(?=[a-z]))"); 
        String[] pt2 = s2.split("((?<=[a-z])(?=[0-9]))|((?<=[0-9])(?=[a-z]))"); 
//pt1 and pt2 arrays will have the string split in alphabets and numbers

        int i=0;
        if(Arrays.equals(pt1, pt2))
            return 0;
        else{
            for(i=0;i<Math.min(pt1.length, pt2.length);i++)
                if(!pt1[i].equals(pt2[i])) {
                    if(!isNumber(pt1[i],pt2[i])) {
                        if(pt1[i].compareTo(pt2[i])>0)
                            return 1;
                        else
                            return -1;
                    }
                    else {
                        int nu1 = Integer.parseInt(pt1[i]);
                        int nu2 = Integer.parseInt(pt2[i]);
                        if(nu1>nu2)
                            return 1;
                        else
                            return -1;
                    }
                }
        }

        if(pt1.length>i)
            return 1;
        else
            return -1;
    }

    private static Boolean isNumber(String n1, String n2) {
          // TODO Auto-generated method stub
        try {
            int nu1 = Integer.parseInt(n1);
            int nu2 = Integer.parseInt(n2);
            return true;
        }
        catch(Exception x) {
            return false;
        }

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String[] examples = {"a1", "b1", "c1", "aa1", "bb1", "cc1", "d1", "e1"};
        List<String> values = new ArrayList<String>(Arrays.asList(examples));

        System.out.println(values);
        Comparator<String> com = (o1,o2) -> {return comparator(o1,o2);}; //lambda expression

        Collections.sort(values,com);
        System.out.println(values);
    }
}

output is [a1, aa1, b1, bb1, c1, cc1, d1, e1]

But , I want

[a1,b1,c1,d1,e1,aa1,bb1,cc1]
soorapadman
  • 4,451
  • 7
  • 35
  • 47
Nix
  • 9
  • 1
  • 2

2 Answers2

7

From the looks of it, this is what you want:

public static void main(String[] args) {
    List<String> a = new ArrayList<>(Arrays.asList("a1", "b1", "c1", "aa1", "bb1", "cc1", "aaa1", "d1", "e1"));
    a.sort(Comparator.nullsFirst(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())));
    System.out.println(a);
}

you first sort by length, then sort strings in length groups.

The output is: [a1, b1, c1, d1, e1, aa1, bb1, cc1, aaa1]

Java 7 version:

Collections.sort(a, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        if (o1 == null) return -1;
        else if (o2 == null) return 1;
        int cmp = Integer.compare(o1.length(), o2.length());
        if (cmp != 0) return cmp;
        return o1.compareTo(o2);
    }
});

Both of the above code examples are null-safe.

Coder-Man
  • 2,391
  • 3
  • 11
  • 19
  • Thank you @Wow :) – Nix Jul 31 '18 at 12:09
  • `thenComparing(Function.identity())` may be a bit confusing. `thenComparing(Comparator.naturalOrder())` is more readable IMO or even `thenComparing(String.CASE_INSENSITIVE_ORDER)` if we don't want to see `a` and `A` as different characters. – Pshemo Jul 31 '18 at 12:11
  • What if ,we want output as a1,a11,a101,a0111,b1,b11,c1,d1,e1,aa1,bb1,aaa1. What will be logic @Wow – Nix Jul 31 '18 at 13:19
  • @Nix you need to specify the language of your strings. I suspect it is [a-z]*[0-9]*. It is unclear if a0111 is greater than or less than a111. – Coder-Man Jul 31 '18 at 13:21
  • sorry for that. but yes in this a0111 is greater than a111 @Wow. I want to arrange it in alphabetical order .i.e. a1,a11,a111,b1,c1,aa1,bb1 – Nix Jul 31 '18 at 13:26
  • @Nix okay, then you need to split your strings into 2 parts, the first part is going to be the letter part and the second part is going to be the digit part, then have this chain of comparisons: for any 2 strings 1) compare the letter parts, 2) then compare the lengths of the digit parts, 3) then convert the digit parts into int's, using Integer.parseInt() and compare them, using Integer.compare. – Coder-Man Jul 31 '18 at 13:30
0

You can do this way also String::length then String::compareToIgnoreCase

String[] examples = {"a1", "b1", "c1", "aa1", "bb1", "cc1", "aaa1", "d1", "e1"};
        List<String> values = new ArrayList<String>(Arrays.asList(examples));
values.sort(Comparator.comparing(String::length).thenComparing(String::compareToIgnoreCase));
System.out.println(values);

Output

[a1, b1, c1, d1, e1, aa1, bb1, cc1, aaa1]
soorapadman
  • 4,451
  • 7
  • 35
  • 47