0

The output of this string should be sorted as follows. The output of this string should be sorted as follows.

public static void main(String[] args) {
String input="";
 List<String> items = Arrays.asList(input.split("\\s*,\\s*"));
   System.out.println("items: " + items);
   Collections.sort(items, new Comparator<String>() {
       public int compare(String o1, String o2) {
           String o1StringPart = o1.replaceAll("\\d", "");
           String o2StringPart = o2.replaceAll("\\d", "");

           if (o1StringPart.equalsIgnoreCase(o2StringPart)) {
               return extractInt(o1) - extractInt(o2);
           }

           return o1.compareTo(o2);
       }

       int extractInt(String s) {
           String num = s.replaceAll("\\D", "");
           // return 0 if no digits found
           return num.isEmpty() ? 0 : Integer.parseInt(num);
       }
   });

   for (String s : items) {
       System.out.println(s);
   }} }
Autumn
  • 13
  • 4

4 Answers4

0

I will provide some tips

In order compare the items 1,20,200-2C,3,32C,32D,4 (this is the default sort order, as string) you need to check if any number is included in the string. This can be done using a regular expression. You can find a lot of examples online with regular expressions that can bring you the numbers in the string back.

Modify your comparator and check if any of the two string that are to be compared include any number and return the appropriate result.

the extractInt method can be similar to as @Pankaj Saini 's suggestion

Integer extractInt(String s) {
    Pattern pattern = Pattern.compile("^\\d+");
    Matcher matcher = pattern.matcher(s);
    if (matcher.find()) {
        String num = matcher.group(0);
        return Integer.parseInt(num);
    }
    return null;
}

The compare method can be like this

public int compare(String o1, String o2) {

     if(extractInt(o1)!=null && extractInt(o2)!=null){
          if(extractInt(o1).equals(extractInt(o2)))
          {
               return o1.substring(extractInt(o1).toString().length())
               .compareTo(o2.substring(extractInt(o2).toString().length()));
          }
          return extractInt(o1).compareTo(extractInt(o2));
    }
    else if(extractInt(o1)!=null)
    {
       return -1;
    }
    else if(extractInt(o2)!=null)
    {
       return 1;
    }
    else{
       return o1.compareTo(o2);
    }
}
Jim_Ktr
  • 129
  • 7
  • I might edit my answer adding some code. If you need any implementation help before I have the answer ready let me know. – Jim_Ktr Nov 19 '19 at 07:54
0

Use the below snippet code. Firstly, you need to compare the integer part of the string and in case the integer part is equal compare the string part.

import java.io.*;
import java.util.*;
import java.util.regex.*;
/*
 * To execute Java, please define "static void main" on a class
 * named Solution.
 *
 * If you need more classes, simply define them inline.
 */

class Solution {
 public static void main(String[] args) {
  String input = "605,2A,401-2A,32C,21F,201A,605A,401-1A,200-2E,583-58D,583/58E,583-57D,542,2B,1,542/2E,605B,32D,3,603,4,6,5,60,201C,542/2D,40,20,50,200-2C,21C,800A,200A,571-573B,51/2,470/1,51/1,571-573C,454-1,444-446";
  List < String > items = Arrays.asList(input.split("\\s*,\\s*"));

  System.out.println("items: " + items);

  Pattern pattern = Pattern.compile("^\\d+");

  Collections.sort(items, new Comparator < String > () {
   public int compare(String o1, String o2) {
    int intDiff = extractInt(o1) - extractInt(o2);

    if (intDiff == 0) {
     return o1.compareTo(o2);
    }

    return intDiff;
   }

   int extractInt(String s) {
    Matcher matcher = pattern.matcher(s);
    if (matcher.find()) {
     String num = matcher.group(0);
     return Integer.parseInt(num);
    }
    return 0;
   }
  });

  for (String s: items) {
   System.out.println(s);
  }
 }
}
Pankaj Saini
  • 752
  • 6
  • 7
  • I think not just method `extractInt(String s)`, method `compare(String o1, String o2)` is supposed to be modified, too. – LHCHIN Nov 19 '19 at 08:02
0

I assume that all the numeric are integer and all the alphabets are A to Z, you can transform those strings which contains / or - into floating points first, then replace all the alphabets to empty strings. Finally, compare their values as Double.
For example, 51/1 will be 51.1 and 571-573B will be 571.573.

Code snippet

public int compare(String o1, String o2) {
    String n1 = o1.replace("-", ".").replace("/", ".").replaceAll("[A-Z]", "");
    String n2 = o2.replace("-", ".").replace("/", ".").replaceAll("[A-Z]", "");

    // This equals above statements
    //String n1 = o1.replaceAll("[-/]", ".").replaceAll("[A-Z]", "");
    //String n2 = o2.replaceAll("[-/]", ".").replaceAll("[A-Z]", "");

    int result = Double.compare(Double.valueOf(n1), Double.valueOf(n2));
    return (result == 0) ? o1.compareTo(o2) : result;
}

This is not the most elegant way, but I think it should work!

LHCHIN
  • 3,679
  • 2
  • 16
  • 34
0

This answer handles comparison between numbers like 20-10A and 20-2A

public static void main(String[] args) {
        String s = "605,2A,401-2A,32C,21F,201A,605A,401-1A,200-2E,583-58D,583/58E,583-57D,542,2B,1,542/2E," +
            "605B,32D,3,603,4,6,5,60,201C,542/2D,40,20,50,200-2C,21C,800A,200A,571-573B,51/2,470/1,51/1," +
            "571-573C,454-1,444-446";

        String[] strings = s.split(",");
        Arrays.sort(strings, App::compare);
        System.out.println(Arrays.deepToString(strings));
}


public static int compare(String o1, String o2) {
    if (startsWithDelim(o1)) return compare(o1.substring(1), o2);
    if (startsWithDelim(o2)) return compare(o1, o2.substring(1));

    List<String> n1 = extractInt(o1);
    List<String> n2 = extractInt(o2);

    if (n1 != null && n2 != null) {
        Integer n1int = Integer.parseInt(n1.get(0));
        Integer n2int = Integer.parseInt(n2.get(0));
        String n1Remaining = n1.get(1);
        String n2Remaining = n2.get(1);
        int intCompare = n1int.compareTo(n2int);
        return intCompare == 0 ? compare(n1Remaining, n2Remaining) : intCompare;
    }

    if (n1 == null && n2 == null)
        return o1.compareTo(o2);
    else if (n1 == null) return -1;
    else return 1;
}

static List<String> extractInt(String s) {

    Pattern pattern = Pattern.compile("^\\d+");
    Matcher matcher = pattern.matcher(s);
    if (matcher.find()) {
        String num = matcher.group(0);
        return List.of(num, s.substring(matcher.end(0)));
    }
    return null;
}

static boolean startsWithDelim(String s) {
    return (s.startsWith("/") || s.startsWith("-"));
}
Silhoutte
  • 57
  • 10
  • I am using java 11. You need to check your version of java. – Silhoutte Nov 19 '19 at 12:07
  • Plus App::compare means compare method define inside class App. So you have to replace App with the class name where you have written the compare method. – Silhoutte Nov 19 '19 at 12:08