# [SOLVED] Rearrange substrings using two criteria

## Issue

Given a String:

``````a - 11 h - 19 l - 18 d - 19
``````

I need to sort its substrings first by numbers (in descending order) and then by letters, so that the result of the sort has the following form:

``````d - 19 h - 19 l - 18 a - 11
``````

## Solution

To solve, the problem must be broken down into subproblems:

1. Break down the input string into substrings
2. Collect each substring into a list
3. Create a comparator that compares the last (numeric) portion of the (sub)string and sorts them in descending order, and then by the beginning portion in ascending order
4. Convert the list of substrings back into a string

## Break down the input string into substrings

``````String regex = "\\w\\s-\\s\\d+";
String input = "a - 11 h - 19 l - 18 d - 19";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
matcher.toMatchResult().groupCount(); // this should return 4 (won't be used in final code)
``````

## Collect each substring into a list

``````List<String> strings = new ArrayList<>();
while (matcher.find()) {
}
``````

The code above will iterate through all of the groups that matched the regex pattern and adds them to a list.

## Create a comparator

``````Comparator<String> compareBySubstring = Comparator.comparing((String s) -> s.substring(s.indexOf(" -")))
.reversed().thenComparing((String s) -> s.substring(0, s.indexOf("-")));
List<String> newList = strings.stream().sorted(compareBySubstring).collect(Collectors.toList());
``````

The comparator I created compares the last portion of the substrings (after the dash) and sorts them in descending order (`reversed()`). Then, the intermediate result is sorted in ascending order from the beginning of the substring up to the dash. Basically it sorts the intermediate result in alphabetical order since the substrings start with a letter.

## Convert the list of substrings back into a string

``````        StringBuilder buffer = new StringBuilder();
newList.forEach(item -> {
buffer.append(item + " "); // done to reinsert the space that separated each substring.
});
``````

I created a test program to run this:

``````public class SortBySubstringDemo {
public static void main(String[] args) {
String regex = "\\w\\s-\\s\\d+";
String input = "a - 11 h - 19 l - 18 d - 19";
System.out.println("Input:\n" + input);

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
List<String> strings = new ArrayList<>();
while (matcher.find()) {
}

Comparator<String> compareBySubstring = Comparator.comparing((String s) -> s.substring(s.indexOf(" -")))
.reversed().thenComparing((String s) -> s.substring(0, s.indexOf("-")));
List<String> newList = strings.stream().sorted(compareBySubstring).collect(Collectors.toList());

StringBuilder buffer = new StringBuilder();
newList.forEach(item -> {
buffer.append(item + " ");
});
String output = buffer.toString().trim();
System.out.println("Output:\n" + output);
}
}
``````

Which results in the following:

``````Input:
a - 11 h - 19 l - 18 d - 19
Output:
d - 19 h - 19 l - 18 a - 11
``````