使用两个条件重新排列子字符串

发布于 2025-01-11 15:33:41 字数 1437 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等待圉鍢 2025-01-18 15:33:41

为了解决这个问题,必须将问题分解为子问题:

  1. 将输入字符串分解为子字符串
  2. 将每个子字符串收集到一个列表中
  3. 创建一个比较器,比较(子)字符串的最后(数字)部分并按降序对它们进行排序,并且然后按升序排列的开始部分
  4. 将子字符串列表转换回字符串

将输入字符串分解为子字符串

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

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()) {
    strings.add(matcher.group());
}

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()) {
            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);
    }
}

Which results in the following:

Input:
a - 11 h - 19 l - 18 d - 19
Output:
d - 19 h - 19 l - 18 a - 11
吃不饱 2025-01-18 15:33:41

针对您的具体示例的一种替代方法是使用 stream

  1. " - " 替换为 " " 来获取由空格分隔的字母和数字的字符串。
  2. 使用" "分割得到一个数组,其中偶数索引为字母,奇数索引为数字。
  3. 创建一个具有偶数索引的 IntStream ,并使用 array[index] 作为键和 将它们映射到 Map.Entry >array[index + 1] 作为值。
  4. 使用比较器对进行排序,该比较器首先比较值,然后比较键。
  5. 使用key + " - " + value 将条目stream 映射到字符串。
  6. 最后,使用 Collectors.joining(" ")收集到一个字符串,并用空格分隔每个“字母 - 数字”

将所有内容总结在一个方法中:

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

One alternative for your specific example is to use stream:

  1. Replace " - " with " " to obtain a string with letters and numbers separated by whitespace.
  2. Split using " " to obtain an array with letters in even indexes and numbers in odd indexes.
  3. Create an IntStream with even indexes and map them to a Map.Entry<String,Integer> using array[index] as key and array[index + 1] as value.
  4. Sort the stream with a comparator that compares values first and then keys.
  5. Map the entry stream to a string with key + " - " + value.
  6. Finally, collect the stream to a string using Collectors.joining(" ") to separate each "letter - number" with a whitespace.

Summarizing all in a method:

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(" "));
}

Test:

String str = "a - 11 h - 19 l - 18 d - 19";

String strSorted = sort(str);

System.out.println(strSorted);

Output:

d - 19 h - 19 l - 18 a - 11
︶葆Ⅱㄣ 2025-01-18 15:33:41
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( " " ) ) );
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( " " ) ) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文