hamid
hamid

Reputation: 2079

Sorting an array of String with custom ordering

I have a String array:

 String[] str = {"ab" , "fog", "dog", "car", "bed"};
 Arrays.sort(str);
 System.out.println(Arrays.toString(str));

If I use Arrays.sort, the output is:

 [ab, bed, car, dog, fog]

But I need to implement the following ordering:

FCBWHJLOAQUXMPVINTKGZERDYS

I think I need to implement Comparator and override compare method:

 Arrays.sort(str, new Comparator<String>() {

        @Override
        public int compare(String o1, String o2) {
            // TODO Auto-generated method stub
            return 0;
        }
    });

How should I go about solving this?

Upvotes: 18

Views: 33501

Answers (4)

Mr.Nestorjava
Mr.Nestorjava

Reputation: 11

Took my time to improve on the selected answer. This is more efficient

public static void customSort(final String order,String[] array){
String[] alphabets={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"};
    String keyword=order;
    for(int g=0; g<alphabets.length; g++){
    String one=alphabets[g];
    if(!keyword.toUpperCase().contains(one)){keyword=keyword+one;}
    }

final String finalKeyword=keyword;
Arrays.sort(array, new Comparator<String>() {

    @Override
   public int compare(String o1, String o2) {
       int pos1 = 0;
       int pos2 = 0;
       for (int i = 0; i < Math.min(o1.length(), o2.length()) && pos1 == pos2; i++) {
          pos1 = finalKeyword.toUpperCase().indexOf(o1.toUpperCase().charAt(i));
          pos2 = finalKeyword.toUpperCase().indexOf(o2.toUpperCase().charAt(i));
       }

       if (pos1 == pos2 && o1.length() != o2.length()) {
           return o1.length() - o2.length();
       }

       return pos1  - pos2  ;
    }
});
//Arrays.sort(array, Collections.reverseOrder());
}

Upvotes: 0

Majid Laissi
Majid Laissi

Reputation: 19808

final String ORDER= "FCBWHJLOAQUXMPVINTKGZERDYS";

Arrays.sort(str, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
       return ORDER.indexOf(o1) -  ORDER.indexOf(o2) ;
    }
});

You can also add:

o1.toUpperCase()

If your array is case in-sensitive.


Apparently the OP wants to compare not only letters but strings of letters, so it's a bit more complicated:

    public int compare(String o1, String o2) {
       int pos1 = 0;
       int pos2 = 0;
       for (int i = 0; i < Math.min(o1.length(), o2.length()) && pos1 == pos2; i++) {
          pos1 = ORDER.indexOf(o1.charAt(i));
          pos2 = ORDER.indexOf(o2.charAt(i));
       }

       if (pos1 == pos2 && o1.length() != o2.length()) {
           return o1.length() - o2.length();
       }

       return pos1  - pos2  ;
    }

Upvotes: 43

Avi
Avi

Reputation: 21866

I would do something like this:

Put the letters in a HashTable (let's call it orderMap). Key is the letter, value is the index in ORDER.

And then:

Arrays.sort(str, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
        int length = o1.length > o2.length ? o1.length: o2.length
        for(int i = 0; i < length; ++i) {
           int firstLetterIndex = orderMap.get(o1.charAt(i));
           int secondLetterIndex = orderMap.get(o2.charAt(i));

           if(firstLetterIndex == secondLetterIndex) continue;

           // First string has lower index letter (for example F) and the second has higher index letter (for example B) - that means that the first string comes before
           if(firstLetterIndex < secondLetterIndex) return 1;
           else return -1;
        }

        return 0;
    }
});

For making it case-insensitive just do toUpperCase() to both strings at the beginning.

Upvotes: 5

Jacek
Jacek

Reputation: 87

Here you can find usefull link:

Using comparator to make custom sort

In your example instead comparing specific attributes of class you nedd to check possition of char in benchmarked String and base on this check if it's greather/equal/smaller.

Upvotes: 0

Related Questions