使用两个条件重新排列子字符串
Rearrange substrings using two criteria
给定一个字符串:
a - 11 h - 19 l - 18 d - 19
我需要先按数字(降序)对它的子串进行排序,然后再按字母排序,这样排序的结果就是下面的形式:
d - 19 h - 19 l - 18 a - 11
要解决,问题必须分解成子问题:
- 将输入字符串分解为子字符串
- 将每个子字符串收集到一个列表中
- 创建一个比较器,比较(子)字符串的最后(数字)部分并按降序对它们进行排序,然后按开始部分按升序排序
- 将子字符串列表转换回字符串
将输入字符串分解为子字符串
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)
将每个子字符串收集到一个列表中
List<String> strings = new ArrayList<>();
while (matcher.find()) {
strings.add(matcher.group());
}
上面的代码将遍历所有匹配正则表达式模式的组,并将它们添加到列表中。
创建比较器
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());
我创建的比较器比较子字符串的最后部分(破折号之后)并按降序对它们进行排序 (reversed()
)。然后,中间结果从子字符串的开头到破折号按升序排序。基本上它按字母顺序对中间结果进行排序,因为子字符串以字母开头。
将子字符串列表转换回字符串
StringBuilder buffer = new StringBuilder();
newList.forEach(item -> {
buffer.append(item + " "); // done to reinsert the space that separated each substring.
});
我为 运行 创建了一个测试程序:
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()) {
strings.add(matcher.group());
}
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);
}
}
结果如下:
Input:
a - 11 h - 19 l - 18 d - 19
Output:
d - 19 h - 19 l - 18 a - 11
您的具体示例的另一种选择是使用 stream
:
- 将
" - "
替换为 " "
以获得由字母和数字以空格分隔的字符串。
- 使用
" "
拆分得到一个 array
,其中字母在偶数索引中,数字在奇数索引中。
- 使用偶数索引创建一个
IntStream
并将它们映射到 Map.Entry<String,Integer>
使用 array[index]
作为键和 array[index + 1]
作为值。
- 使用先比较值然后比较键的比较器对
stream
进行排序。
- 将条目
stream
映射到具有 key + " - " + value
的字符串。
- 最后,使用
Collectors.joining(" ")
将 stream
收集到一个字符串中,用空格分隔每个 "letter - number"
。
总结在一个方法中:
public static String sort(String str) {
String[] arr = str.replaceAll(" - ", " ").split(" ");
Comparator<Map.Entry<String, Integer>> comparator = Comparator
.comparingInt(Map.Entry<String, Integer>::getValue).reversed()
.thenComparing(Map.Entry::getKey);
return IntStream.range(0, arr.length).filter(i -> i % 2 == 0)
.mapToObj(i -> Map.entry(arr[i], Integer.parseInt(arr[i + 1])))
.sorted(comparator).map(entry -> entry.getKey() + " - " + entry.getValue())
.collect(Collectors.joining(" "));
}
测试:
String str = "a - 11 h - 19 l - 18 d - 19";
String strSorted = sort(str);
System.out.println(strSorted);
输出:
d - 19 h - 19 l - 18 a - 11
String s = "a - 11 h - 19 l - 18 d - 19";
record Pair(String string, int number) { }
System.out.println( new Scanner( s ).findAll( "(\w)\s-\s(\d+)" )
.map( matchResult -> new Pair( matchResult.group( 1 ), Integer.parseInt( matchResult.group( 2 ) ) ) )
.sorted( Comparator.<Pair>comparingInt( Pair::number ).reversed().thenComparing( Pair::string ) )
.map( pair -> pair.string() + " - " + pair.number() )
.collect( Collectors.joining( " " ) ) );
给定一个字符串:
a - 11 h - 19 l - 18 d - 19
我需要先按数字(降序)对它的子串进行排序,然后再按字母排序,这样排序的结果就是下面的形式:
d - 19 h - 19 l - 18 a - 11
要解决,问题必须分解成子问题:
- 将输入字符串分解为子字符串
- 将每个子字符串收集到一个列表中
- 创建一个比较器,比较(子)字符串的最后(数字)部分并按降序对它们进行排序,然后按开始部分按升序排序
- 将子字符串列表转换回字符串
将输入字符串分解为子字符串
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)
将每个子字符串收集到一个列表中
List<String> strings = new ArrayList<>();
while (matcher.find()) {
strings.add(matcher.group());
}
上面的代码将遍历所有匹配正则表达式模式的组,并将它们添加到列表中。
创建比较器
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());
我创建的比较器比较子字符串的最后部分(破折号之后)并按降序对它们进行排序 (reversed()
)。然后,中间结果从子字符串的开头到破折号按升序排序。基本上它按字母顺序对中间结果进行排序,因为子字符串以字母开头。
将子字符串列表转换回字符串
StringBuilder buffer = new StringBuilder();
newList.forEach(item -> {
buffer.append(item + " "); // done to reinsert the space that separated each substring.
});
我为 运行 创建了一个测试程序:
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()) {
strings.add(matcher.group());
}
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);
}
}
结果如下:
Input:
a - 11 h - 19 l - 18 d - 19
Output:
d - 19 h - 19 l - 18 a - 11
您的具体示例的另一种选择是使用 stream
:
- 将
" - "
替换为" "
以获得由字母和数字以空格分隔的字符串。 - 使用
" "
拆分得到一个array
,其中字母在偶数索引中,数字在奇数索引中。 - 使用偶数索引创建一个
IntStream
并将它们映射到Map.Entry<String,Integer>
使用array[index]
作为键和array[index + 1]
作为值。 - 使用先比较值然后比较键的比较器对
stream
进行排序。 - 将条目
stream
映射到具有key + " - " + value
的字符串。 - 最后,使用
Collectors.joining(" ")
将stream
收集到一个字符串中,用空格分隔每个"letter - number"
。
总结在一个方法中:
public static String sort(String str) {
String[] arr = str.replaceAll(" - ", " ").split(" ");
Comparator<Map.Entry<String, Integer>> comparator = Comparator
.comparingInt(Map.Entry<String, Integer>::getValue).reversed()
.thenComparing(Map.Entry::getKey);
return IntStream.range(0, arr.length).filter(i -> i % 2 == 0)
.mapToObj(i -> Map.entry(arr[i], Integer.parseInt(arr[i + 1])))
.sorted(comparator).map(entry -> entry.getKey() + " - " + entry.getValue())
.collect(Collectors.joining(" "));
}
测试:
String str = "a - 11 h - 19 l - 18 d - 19";
String strSorted = sort(str);
System.out.println(strSorted);
输出:
d - 19 h - 19 l - 18 a - 11
String s = "a - 11 h - 19 l - 18 d - 19";
record Pair(String string, int number) { }
System.out.println( new Scanner( s ).findAll( "(\w)\s-\s(\d+)" )
.map( matchResult -> new Pair( matchResult.group( 1 ), Integer.parseInt( matchResult.group( 2 ) ) ) )
.sorted( Comparator.<Pair>comparingInt( Pair::number ).reversed().thenComparing( Pair::string ) )
.map( pair -> pair.string() + " - " + pair.number() )
.collect( Collectors.joining( " " ) ) );