【问题标题】:How do I sort lexicographically with sorted(comparator) method?如何使用 sorted(comarator) 方法按字典顺序排序?
【发布时间】:2021-05-15 14:51:06
【问题描述】:

我有这个函数可以按数字顺序对我的数据行进行排序,但问题是它排序的键是由字母和数字组成的:

void writeData(Map<String, Params> data) {
    .
    .
    StringBuilder sb = new StringBuilder();
    data.values()
        .stream()
        .sorted(Comparator.comparing(Params::getIdx))
        .forEach(r -> {
            sb.append(System.lineSeparator());
            sb.append(r.getCSVRow());
        });
    .
    .
}

例如我有字符串: "A100","A101", "A99".

我得到的订单:

A100
A101
A99

我想要的顺序:

A99
A100
A101

如何更改此功能? 由于某种原因,我没有使用thenCompare 的选项。 (不过我已经读过)。

【问题讨论】:

    标签: java string sorting dictionary


    【解决方案1】:

    按字典顺序这是正确的排序,因为 character 9character 1 之后。您应该将这些字符串拆分为非数字和数字部分,并分别对它们进行排序:数字作为数字,字符串作为字符串。排序后,您可以将这些部分重新组合成一个字符串并获得一个排序数组。例如:

    // assume a string consists of a sequence of
    // non-numeric characters followed by numeric characters
    String[] arr1 = {"A100", "A101", "A99", "BBB33", "C10", "T1000"};
    
    String[] arr2 = Arrays.stream(arr1)
            // split string into an array of two
            // substrings: non-numeric and numeric
            // Stream<String[]>
            .map(str -> str
                    // add some delimiters to a non-empty
                    // sequences of non-numeric characters
                    .replaceAll("\\D+", "$0\u2980")
                    // split string into an array
                    // by these delimiters
                    .split("\u2980"))
            // parse integers from numeric substrings,
            // map as pairs String-Integer
            // Stream<Map.Entry<String,Integer>>
            .map(row -> Map.entry(row[0], Integer.parseInt(row[1])))
            // sort by numbers as numbers
            .sorted(Map.Entry.comparingByValue())
            // intermediate output
            //C=10
            //BBB=33
            //A=99
            //A=100
            //A=101
            //T=1000
            .peek(System.out::println)
            // join back into one string
            .map(entry -> entry.getKey() + entry.getValue())
            // get sorted array
            .toArray(String[]::new);
    
    // final output
    System.out.println(Arrays.toString(arr2));
    // [C10, BBB33, A99, A100, A101, T1000]
    

    另见:
    How do I relate one array input to another?
    How to remove sequence of two elements from array or list?

    【讨论】:

      【解决方案2】:

      解析出数字:

      Comparator.comparingInt(v -> Integer.parseInt(v.substring(1))
      

      (假设前缀始终为 1 个字符)

      【讨论】:

      • 我不怕。但实际上是两个字符,然后是昏迷,然后是数字……
      • 这不是您在问题中显示的内容。尽管如此,两个字符和一个逗号的前缀的固定长度为 3,因此您只需将 1 更改为 3
      • 我现在得到的是 26 出于某种原因(例如)在 3 之前。我得到这个订单:26、27、28、29、3、30、31、32。而我想要:3、26、27、28、29、30、31、32。你能帮忙吗?
      • @gus Stream.of("AA,3", "AA,26").sorted(Comparator.comparingInt(v -&gt; Integer.parseInt(v.substring(3)))).forEach(System.out::println) 将按AA,3 AA,26: ideone.com/G9GzKA 的顺序打印。我不知道你做了什么来得到你报告的订单。
      猜你喜欢
      • 2013-03-07
      • 2010-10-24
      • 1970-01-01
      • 2018-09-26
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      • 2019-09-21
      • 2020-08-02
      相关资源
      最近更新 更多