【问题标题】:Compare partially-numeric string without casting比较部分数字字符串而不进行强制转换
【发布时间】:2017-09-06 14:44:16
【问题描述】:

我用谷歌搜索了一下,但无法找到解决这种特定问题的方法。我有一个List 的 POJO,它确实有一个名为 displayCode(字符串类型)的字段。 displayCode 可以有不同的格式。一些例子:

622
622-S
622-1
623 
624
625
625-S
625-1
625-1-S
625-2
625-2-S

排序后,它们也应该按上图所示的顺序排列。使用普通的s1.compareTo(s2); 我会收到这样的订单:

1
10
100
101
102
...

这显然不适合我的需要。可悲的是,我没有计划如何以任何顺利的方式实现这一目标(也没有其他方式)。另请注意,我无法使用 Java 8 中的任何内容。

用于测试目的的代码(你可以玩弄它):

List<String> s = new ArrayList<String>(Arrays.asList(new String[] { "622", "622-S", "622-1", "623", "625",
        "625-S", "625-1", "625-1-S", "625-2", "625-2-S", "6", "60", "666", "1", "2", "3" }));
Collections.sort(s,new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {

        return 0;
    }
});
System.out.println(s);

编辑: 我的第一个想法是将直到第一个 - 的数字转换为一个 int 并进行比较,然后按照我的方式处理其他部分。然而这听起来并不顺利。

【问题讨论】:

  • 在担心顺利之前,您可能需要专注于有效
  • 你唯一的问题似乎是最后的 S,因为正常的比较会给你:1、2、3、6、60、622、622-1、622-S、623、625 , 625-1, 625-1-S, 625-2, 625-2-S, 625-S, 666
  • 您能否对上面实际列出的数组中的元素显示“错误”排序?
  • @MárioFernandes:不,因为625-10-S 会在625-2-S 之前出现(OP 强调了这个问题,问题中的数字位数不同,所以我们可以假设不仅仅是实际引用的示例代码中的数字)。
  • @T.J.Crowder 你确实是对的

标签: java compare comparator string-comparison


【解决方案1】:

除了隔离每个字符串的数字部分,转换为数字,比较它们,只有当它们相等时才对字符串进行字典比较。

例如,按照这些思路(概念,可能需要调整):

@Override
public int compare(String o1, String o2) {
    String[] p1 = o1.split(" ", 2);
    String[] p2 = o2.split(" ", 2);
    try {
        int n1 = Integer.parseInt(p1[0]);
        int n2 = Integer.parseInt(p2[0]);
        if (n1 != n2) {
            return n1 - n2;
        }
        boolean s1 = p1.length > 1 && p1.equals("S");
        boolean s2 = p2.length > 1 && p2.equals("S");
        if (s1 && !s2) {
            return -1;
        }
        if (!s1 && s2) {
            return 1;
        }
    } catch (NumberFormatException e) {
    }
    return o1.compareTo(o2);
}

【讨论】:

  • 听起来我必须走的路
  • 考虑 POJO 构造器/设置器将 displayCode 拆分为数字和字符串部分以作为单独的字段保存。这将简化比较方法,如果List 很大,可能会使排序更快。
【解决方案2】:

这可能会对你有所帮助。

Collections.sort(s, new Comparator<String>() {

            public int compare(String o1, String o2) {
                int returnValue = -1;

                Integer left = returnIfNumeric(o1);
                Integer right = returnIfNumeric(o2);

                // if both values are number
                if (left != null && right != null) {
                    if (left > right)
                        returnValue = 1;
                    else if (left == right)
                        returnValue = 0;
                    else
                        returnValue = -1;
                } 
                // if both values are string
                else if (left == null && left == right) {
                    return o1.compareTo(o2);
                }
                // if left is number
                else if (left != null) {
                    returnValue = -1;
                }
                // if left is string
                else {
                    returnValue = 1;
                }

                return returnValue;
            }
        });

    }

    public static Integer returnIfNumeric(String str) {
        Integer number = null;
        try {
            number  = Integer.valueOf(str);
        } catch (NumberFormatException nfe) {
            number = null;
        }
        return number;
    }

【讨论】:

    【解决方案3】:

    Java 字符串有一个split 方法,可以用来隔离 POJO 的数字部分;然后您可以使用parseInt 将 POJO 获取为整数,这将使您可以轻松地进行排序。

    【讨论】:

      猜你喜欢
      • 2017-08-02
      • 2015-07-12
      • 1970-01-01
      • 2012-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-14
      • 1970-01-01
      相关资源
      最近更新 更多