简体   繁体   中英

Sort half of a String ArrayList based on a substring of each string

I have a String ArrayList of sizes, for example

[12, 10L, 10, 10R, 10S, 10L]

The output should be

[10S, 10R, 10L, 10, 12]

So basically sizes must be first sorted by number - (1,2,3,4,5... etc) then by letters.

I managed to get the numbers to sort, so my current output for the input above is

10L, 10, 10R, 10S, 10L, 12

if a letter is missing, then it is the largest (see output above - 10 is after 10L - 10S < 10R < 10L < 10 < 12. )

How should i code a comparator that allows me to do this?

Consider an input array, sizes. This array contains product sizes in the format AB, where:

A is a mandatory integer B is an optional character in [S,R,L] Sizes must first be ordered from smallest to largest by A, and then by B in the order S

I assume finalList list has the sort data.

10L, 10, 10R, 10S, 10L, 12

Use regex to match the integer, merge the list of alphanumerics and numbers .

On your sorted list, run this

List<String> numberList= new ArrayList<String>(); // store number list
List<String> sizeList= new ArrayList<String>(); // store alphanumerics
for(String value: finalList){

  if(!value.matches("[0-9]+")){  // if contains characters
     sizeList.add(value);
   }
   else{
        numberList.add(value);
  }
}

sizeList.addAll(numberList); 

sizeList has what you need

Try this if it works for your testcases. We can always refine it if needed. (Added a helper method)

List<String> list = new ArrayList<>(Arrays.asList("12","10L","10","10R","10S","10L","14L","14","8","12S"));
List<String> orderArray = new ArrayList<>(Arrays.asList("S", "R", "L"));

List<String> sortedList = list.stream()
            .sorted(Comparator.comparing(str -> Integer.parseInt(((String)str).replaceAll("[A-Z]*","")))
                    .thenComparing(str -> getAnInt(orderArray, (String) str)))
            .distinct()
            .collect(Collectors.toList());

System.out.println(sortedList);

private int getAnInt(List<String> orderArray, String str) {
    int i = orderArray.indexOf(str.substring(str.length() - 1));
    if (i == -1) return Integer.MAX_VALUE;
    return i;
}

Output: [8, 10S, 10R, 10L, 10, 12S, 12, 14L, 14]

if you don't want to use streams:

List<String> list = new ArrayList<>(Arrays.asList("12","10L","10","10R","10S","10L","14L","14","8","12S"));
List<String> orderArray = new ArrayList<>(Arrays.asList("S", "R", "L"));

list.sort(new Comparator<String>() {
        @Override
        public int compare(String lhs, String rhs) {
            int lInt = Integer.parseInt(lhs.replaceAll("[A-Z]*", ""));
            int rInt = Integer.parseInt(rhs.replaceAll("[A-Z]*", ""));
            if (lInt != rInt) {
               return lInt - rInt;
            } else {
                return getAnInt(orderArray, lhs) - getAnInt(orderArray, rhs);
            }
        }
    });

System.out.println(list);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM