1

I have an array of strings like

{"Bart4", "Bart5", "Bart6", "Bart7", "Bart8", "Bart9", "Bart10",
 "Lisa", "Marge", "Homer", "Bart", "Bart1", "Bart2", "Bart3", "Bart11", "Bart12"}

I need to sort it in this order

{"Bart", "Bart1", "Bart2", "Bart3", "Bart4", "Bart5", "Bart6",
 "Bart7", "Bart8", "Bart9", "Bart10", "Bart11", "Bart12", "Homer","Lisa", "Marge"}

If I use standard sort function in java I get

 {"Bart", "Bart1", "Bart10", "Bart11", "Bart12", "Bart2", "Bart3",
  "Bart4", "Bart5", "Bart6", "Bart7", "Bart8", "Bart9","Homer","Lisa", "Marge"}

Is there a predefined function for this in Java?

If I want to design customized sorting how do I go about it?

Edit: I have added source code below with a lot of compilation errors

Source Code-

import java.util.*;

public class Main{
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
        @Override
        public int compareTo(String s1,String s2){
            int len1,len2,len,i,num1,num2;

            len1 = s1.length();
            len2 = s2.length();
            len = len1 > len2 ? len2 : len1;

            if(s1.equals(s2))
                return 0;

            for(i = 0; i < len; i++){
                if(isLetter(s1.charAt(i)) && isLetter(s2.charAt(i))){
                        if(s1.charAt(i) < s2.charAt(i))
                            return 1;
                        else if(s1.charAt(i) > s2.charAt(i))
                            return -1;
                }
                else if(isLetter(s1.charAt(i)) && isDigit(s2.charAt(i)))
                    return -1;

                else if(isDigit(s1.charAt(i)) && isLetter(s2.charAt(i)))
                    return 1;

                else if(isDigit(s1.charAt(i)) && isDigit(s2.charAt(i))){
                    num1 = Integer.parseInt(s1.substring(i,len1));
                    num2 = Integer.parseInt(s2.substring(i,len2));
                    return num1 > num2 ? -1 : 1;
                }       
            }
        }
    });

    public String newMember(String [] existingNames, String newName){
        int lv,arr_len,str_len,val,count,flag,setflag;

        count=-1;
        flag=1;
        setflag=0;
        arr_len = existingNames.length;
        str_len = newName.length();

        Arrays.sort(existingNames);
        print(existingNames,arr_len);

        for(lv = 0; lv < arr_len && flag == 1; lv++){
            if(existingNames[lv].startsWith(newName)){
                setflag = 1;
                count++;
                val = getValue(existingNames[lv],str_len);
                if(count < val && count == 0)
                    return newName;
                if(count < val && count != 0)
                    return newName.concat(count+"");
            }
            if(setflag == 1 && !existingNames[lv].startsWith(newName))
                flag = 0;
        }

        if(count == -1)
            return newName;

        return newName.concat(count + 1 + "");
    }

    public void print(String [] arr,int len){
        for(int i=0; i<len; i++)
            System.out.println(arr[i]);
    }

    public int getValue(String name,int len){
        int str_len = name.length();
        if(str_len == len)
            return 0;
        else
            return Integer.parseInt(name.substring(len,str_len));
    }

    public static void main(String [] args){
        String [] arr = {"Bart4", "Bart5", "Bart6", "Bart7", "Bart8", "Bart9", "Bart10","Lisa", "Marge", 
                        "Homer", "Bart", "Bart1", "Bart2", "Bart3","Bart11", "Bart12"};
        String name = "Bart";
        System.out.println(newMember(arr,name));
    }
}

Compilation Errors:

compilation info
Main.java:4: error: <identifier> expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                         ^
Main.java:4: error: <identifier> expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                     ^
Main.java:4: error: illegal start of type
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                       ^
Main.java:4: error: ')' expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                          ^
Main.java:4: error: ';' expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                                     ^
Main.java:4: error: <identifier> expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                                            ^
Main.java:4: error: illegal start of type
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                                             ^
Main.java:4: error: <identifier> expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                                              ^
Main.java:4: error: ';' expected
    java.util.Arrays.sort(stringArray ,new Comparator<String>(){
                                                               ^
Main.java:33: error: class, interface, or enum expected
    });
     ^
Main.java:35: error: class, interface, or enum expected
    public String newMember(String [] existingNames, String newName){
           ^
Main.java:38: error: class, interface, or enum expected
        count=-1;
        ^
Main.java:39: error: class, interface, or enum expected
        flag=1;
        ^
Main.java:40: error: class, interface, or enum expected
        setflag=0;
        ^
Main.java:41: error: class, interface, or enum expected
        arr_len = existingNames.length;
        ^
Main.java:42: error: class, interface, or enum expected
        str_len = newName.length();
        ^
Main.java:44: error: class, interface, or enum expected
        Arrays.sort(existingNames);
        ^
Main.java:45: error: class, interface, or enum expected
        print(existingNames,arr_len);
        ^
Main.java:47: error: class, interface, or enum expected
        for(lv = 0; lv < arr_len && flag == 1; lv++){
        ^
Main.java:47: error: class, interface, or enum expected
        for(lv = 0; lv < arr_len && flag == 1; lv++){
                    ^
Main.java:47: error: class, interface, or enum expected
        for(lv = 0; lv < arr_len && flag == 1; lv++){
                                               ^
Main.java:50: error: class, interface, or enum expected
                count++;
                ^
Main.java:51: error: class, interface, or enum expected
                val = getValue(existingNames[lv],str_len);
                ^
Main.java:52: error: class, interface, or enum expected
                if(count < val && count == 0)
                ^
Main.java:54: error: class, interface, or enum expected
                if(count < val && count != 0)
                ^
Main.java:56: error: class, interface, or enum expected
            }
            ^
Main.java:59: error: class, interface, or enum expected
        }
        ^
Main.java:64: error: class, interface, or enum expected
        return newName.concat(count + 1 + "");
        ^
Main.java:65: error: class, interface, or enum expected
    }
    ^
Main.java:67: error: class, interface, or enum expected
    public void print(String [] arr,int len){
           ^
Main.java:68: error: class, interface, or enum expected
        for(int i=0; i<len; i++)
                     ^
Main.java:68: error: class, interface, or enum expected
        for(int i=0; i<len; i++)
                            ^
Main.java:70: error: class, interface, or enum expected
    }
    ^
Main.java:72: error: class, interface, or enum expected
    public int getValue(String name,int len){
           ^
Main.java:74: error: class, interface, or enum expected
        if(str_len == len)
        ^
Main.java:76: error: class, interface, or enum expected
        else
        ^
Main.java:78: error: class, interface, or enum expected
    }
    ^
Main.java:80: error: class, interface, or enum expected
    public static void main(String [] args){
                  ^
Main.java:83: error: class, interface, or enum expected
        String name = "Bart";
        ^
Main.java:84: error: class, interface, or enum expected
        System.out.println(newMember(arr,name));
        ^
Main.java:85: error: class, interface, or enum expected
    }
    ^
41 errors
  stdout

How to fix this?

user3409814
  • 245
  • 1
  • 4
  • 12
  • Custom sorting/ordering - http://stackoverflow.com/q/16541314/2459730 – Andrew_CS Aug 14 '14 at 21:30
  • Related - http://stackoverflow.com/questions/1262239/natural-sort-order-string-comparison-in-java-is-one-built-in – Bhesh Gurung Aug 14 '14 at 21:31
  • 1
    A standard sort would put `"Homer"` before `"Lisa"`. – rgettman Aug 14 '14 at 21:33
  • You can write your own comparator – Xinzz Aug 14 '14 at 21:40
  • To design a custom comparator, you will need to have a clear definition of what strings you will accept and how the comparator will work. For example, if an input string must be a sequence of letters optionally followed by a sequence of digits, you can use that information in the comparator but should throw an exception for a string that doesn't follow the form. If an input string could have digits anywhere in it, you'll need to come up with a definition for which one would come first. Plus you'll need to explain why `Homer` should be last... – ajb Aug 14 '14 at 21:50
  • Try my solution :) Regular expressions simplify the logic. – bdunn Aug 15 '14 at 13:00
  • @bdunn I did go through the solution. I am not able to understand what regex means? How to use it? etc. So didn't use it. Could you please look into compilation errors and let me know the problem in that code. It would be helpful. – user3409814 Aug 15 '14 at 17:18
  • I provided working code, copy and paste that and you're up and running. Regex is short for regular expression, it's a powerful way to search and parse strings based on patterns. I highly suggest you Google it too learn more, it's a very useful tool. – bdunn Aug 15 '14 at 17:33
  • @bdunn I did give a quick read on regex from this http://www.vogella.com/tutorials/JavaRegularExpressions/article.html. Now your code seams really simple and easy. In the regex expr "^([\\D]+)([0-9]+)$", ^([\\D]+) is for no digits; (1) In ([0-9]+) why have you used + ? It should be * since digits can be none or many; (2) What is use of $ ? – user3409814 Aug 15 '14 at 20:34
  • @bdunn Using * as [0-9]* is giving exception though. – user3409814 Aug 15 '14 at 20:37
  • @user3409814 @user3409814 Exactly, `\D+` matches any non-digit character, and I used `[0-9]+` to match any number character one or more times (I could have also used `[\d]+`). A "special" comparison is only done if both of these groups match (i.e. there is a string followed by a sequence of digits). If they do match, and the first group (the string before the trailing digits) matches, convert the digits to int and compare. If the regex doesn't match I do a normal comparison with `return o1.compareTo(o2);`. No need for `[0-9]*`. – bdunn Aug 15 '14 at 20:42
  • @user3409814 Also, `^` matches the start of a string and `$` matches the end of a string. – bdunn Aug 15 '14 at 20:43

3 Answers3

4

For custom sorting you can use a Collection and implement a Comparator. For example:

String [] a = {"Bart4", "Bart5", "Bart6", "Bart7", "Bart8", 
    "Bart9", "Bart10", "Lisa", "Marge", "Homer", "Bart", 
    "Bart1", "Bart2", "Bart3", "Bart11", "Bart12"};

java.util.Arrays.sort(a, new Comparator<String>() {

    final String regex = "^([\\D]+)([0-9]+)$";
    Pattern p = Pattern.compile(regex);
    Matcher m1, m2;

    @Override
    public int compare(String o1, String o2) {
        m1 = p.matcher(o1);
        m2 = p.matcher(o2);

        if (m1.matches() && m2.matches()) {
            if (m1.group(1).equals(m2.group(1))) 
                return Integer.valueOf(m1.group(2)).compareTo(Integer.valueOf(m2.group(2)));
        } 

        return o1.compareTo(o2);
    }
});

for (String s : a) System.out.println(s);

Output:

Bart
Bart1
Bart2
Bart3
Bart4
Bart5
Bart6
Bart7
Bart8
Bart9
Bart10
Bart11
Bart12
Homer
Lisa
Marge

EDIT: Sorted the array directly instead of using Arrays.asList().

bdunn
  • 472
  • 4
  • 19
1

You will have to use a Comparator and define your own logic.The Comparator will take two String as inputs .

String [] stringArray = {"Bart4", "Bart5", "Bart6", "Bart7", "Bart8", "Bart9", "Bart10",
 "Lisa", "Marge", "Homer", "Bart", "Bart1", "Bart2", "Bart3", "Bart11", "Bart12"};

java.util.Arrays.sort(stringArray ,new Comparator<String>(){

            @Override
            public int compare(String s1, String  s2) {
                //You will need to build your logic here ..You will have to extract numbers //from the string and compare the substring and the number with other sub string and number
            }
});
Kumar Abhinav
  • 6,565
  • 2
  • 24
  • 35
  • I followed your approach but getting compilation errors as listed above – user3409814 Aug 15 '14 at 08:25
  • @user3409814 You will have to write your logic in compare method and accordingly return the int value.If String s1 should come before String 2,you will have to return int value less than 0,if they are equal you should return 0 else value greater than 0.Thats the sortng logic of a Comparator.See documentation of compare method of Comparator – Kumar Abhinav Aug 15 '14 at 12:23
  • I have looked into documentation of Comparator and did make edits to return 0 in compareTo. Could you please look into the compilation errors and point out changes required. That would be helpful. :) – user3409814 Aug 15 '14 at 17:14
0

Can you change Bart1 to Bart01? If you can, a simple alphabetic sorting is enough.

user3906040
  • 651
  • 1
  • 8
  • 12