【问题标题】:Java Custom Size String ComparatorJava 自定义大小字符串比较器
【发布时间】:2021-07-14 11:16:32
【问题描述】:

我有以下字符串:

50ml,100g,3.5ml,10g,0.4g,320ml 我需要按以下顺序订购:

0.4g,10g,100g,3.5ml,50ml,320ml

标准是按字母顺序排列尺寸类型(g 在 m 之前),然后是实际尺寸 ASCENDANT (0.4 10g 100g)

如何使用 Comparator 实现这一点?

protected int compareInstances(String instance1, String instance2) {
    return 0;
}

【问题讨论】:

  • 到目前为止你尝试过什么?你在哪里卡住了?只有“ml”和“g”还是可以是任何东西?
  • 可以是任何字母。我不知道如何按多个条件比较字符串

标签: java compare comparator string-comparison


【解决方案1】:

这里可能最简单(但不是最漂亮)的方法是将值简单地拆分为前缀(实际值)和后缀(测量值),然后分别进行比较。

所以我实现了一个Comparator<String>,它将给定的值分成前缀和后缀,然后首先按字母顺序比较后缀。 (免责声明:大写字母将被视为比小写字母“更小”)如果它们相等,则比较前缀值。

下面是一个描述逻辑的小例子:

import java.util.Arrays;
import java.util.Comparator;

public class Test {

    public static void main(String[] args) {
        String input = "50ml,100g,3.5ml,10g,0.4g,320ml,32.3a,3.6ml";
        String[] splitInput = input.split(",");
        System.out.println("Before:\t" + Arrays.toString(splitInput));
        Arrays.sort(splitInput, new MyComparator());
        System.out.println("After:\t" + Arrays.toString(splitInput));
    }

    static class MyComparator implements Comparator<String> {

        @Override
        public int compare(String o1, String o2) {
            // extract the suffix by removing the digits and dots
            String suffix1 = o1.replaceAll("[\\d\\.]", "");
            String suffix2 = o2.replaceAll("[\\d\\.]", "");
            if (suffix1.compareTo(suffix2) != 0) {
                return suffix1.compareTo(suffix2); // String#compareTo
            }
            // extract the prefix by removing the characters
            double value1 = Double.parseDouble(o1.replaceAll("[A-Za-z]", ""));
            double value2 = Double.parseDouble(o2.replaceAll("[A-Za-z]", ""));
            // compare the double values
            return (int) Double.compare(value1, value2);
        }
    }

}

输出:

Before: [50ml, 100g, 3.5ml, 10g, 0.4g, 320ml, 32.3a, 3.6ml]
After:  [32.3a, 0.4g, 10g, 100g, 3.5ml, 3.6ml, 50ml, 320ml]

【讨论】:

  • 我猜这会显示 1L 大于 1200ml。所以,如果输入是干净的,那么这很好。
  • 你是对的。如果后缀为大写,则与String#compareTo() 的小写后缀相比,它将被视为“更小”。
【解决方案2】:

有很多方法可以做到这一点。我将编写一个简单的排序方法来排序并返回排序后的字符串,而不是单独的比较器。当然,返回值可以修改为返回任何数据结构。

String s = "50ml,100g,3.5ml,10g,0.4g,320ml";
    
String result = sort(s);
System.out.println(result);

打印

0.4g,10g,100g,3.5ml,50ml,320ml
  • 此方法首先在逗号分隔符处拆分字符串。
  • 然后流式传输这些字符串,首先将它们在数字和字母之间拆分(我认为最好在比较器之外执行此操作以减少重复拆分)。
  • 然后对值进行排序,首先按单位,然后按金额,然后重新加入其原始格式。
public static String sort(String s) {
    String[] amts = s.split(",");
    return Arrays.stream(amts)
            .map(amt -> amt.trim().toLowerCase().split("(?<=\\d)(?=\\p{Lower})"))
            .sorted(Comparator.comparing((String[] arr) -> arr[1])
                    .thenComparing(
                            arr -> Double.parseDouble(arr[0])))
            .map(arr -> arr[0] + arr[1])
            .collect(Collectors.joining(","));
}
  • 如果需要数组,请将返回类型更改为String[]
  • 并将.collect(Collectors.joining(",")); 更改为.toArray(String[]::new);

【讨论】:

    猜你喜欢
    • 2011-12-26
    • 2020-11-27
    • 1970-01-01
    • 2018-12-22
    • 2013-06-30
    • 1970-01-01
    • 2011-11-08
    • 2016-01-29
    相关资源
    最近更新 更多