【问题标题】:Sorting Strings that contains number in Java [duplicate]在Java中对包含数字的字符串进行排序[重复]
【发布时间】:2012-12-08 01:14:33
【问题描述】:

我对字符串的默认比较器(在 SortedSet 中)有疑问。问题是默认比较器不会对包含数字的良好字符串进行排序,即: 在集合中我有:

room1, room2, room100

自然排序应该和上面一样,但在集合中我有:

room1, room100, room2

我知道为什么会这样,但我不知道如何改变它。

【问题讨论】:

  • 您需要创建一个自定义比较器
  • 我知道,但我不知道如何比较它。知道我正在尝试这个: >private int compareNumbers(String o1, String o2) { Pattern numberPattern = Pattern.compile(PATTERN);匹配器 matcher1 = numberPattern.matcher(o1);匹配器 matcher2 = numberPattern.matcher(o2); int i1 = Integer.parseInt(matcher1.group()); int i2 = Integer.parseInt(matcher2.group()); System.out.println(i1 + " " + i2);返回 i1 - i2; }
  • 您需要做一些假设,例如,所有字符串的格式是否为 ?或决定您的格式到底是什么,然后您才能编写比较器

标签: java sorting


【解决方案1】:

您可以实现一个比较器并将其传递给 set 构造函数。 见http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html

如果您的所有字符串都采用 room[number] 的形式,您可以剥离“room”解析数字并进行比较。
或者-您可以将整数存储在您的设置中并使用“房间”前缀打印它们。

【讨论】:

  • 但我不知道如何比较它。一些正则表达式?
  • 字符串总是以 room[number] 的形式出现吗?
【解决方案2】:

试试这个。我假设你的字符串开头总是有“房间”。

    List<String> list = Arrays.asList("room1", "room100", "room2");
    Collections.sort(list, new Comparator<String>()
    {
        @Override
        public int compare(String o1, String o2)
        {
            return new Integer(o1.replaceAll("room", ""))
                .compareTo(new Integer(o2.replaceAll("room", "")));
        }

    });

【讨论】:

    【解决方案3】:

    这是我的Comparator 实现这种排序: (字符串可以从任何字符开始)

    public class StringNumberComparator implements Comparator<String>{
    
        @Override
        public int compare(String o1, String o2) {
        int i1 = this.getRearInt(o1);
        int i2 = getLeadingInt(o2);
        String s1 = getTrailingString(o1);
        String s2 = getTrailingString(o2);
    
        if(i1==i2)
             return s1.compareTo(s2);
        if(i1>i2)
             return 1;
        else if(i1<i2)
                return -1;
        return 0;
        }
    
        private int getRearInt(String s) {
        s=s.trim();
        int i=Integer.MAX_VALUE;
        try {
                 i = Integer.parseInt(s.split("[^0-9]+")[1]);
        } catch(ArrayIndexOutOfBoundsException e) {
    
        } catch(NumberFormatException f) {
                return i;
        }
    
        return i;
        }
    
        private String getTrailingString(String s) {
            return  s.replaceFirst("[0-9]", "");
        }
    }
    

    【讨论】:

      【解决方案4】:

      试试这个比较器,它会删除所有非数字字符,然后将剩余的字符作为数字进行比较:

      Collections.sort(strings, new Comparator<String>() {
          public int compare(String o1, String o2) {
              return extractInt(o1) - extractInt(o2);
          }
      
          int extractInt(String s) {
              String num = s.replaceAll("\\D", "");
              // return 0 if no digits found
              return num.isEmpty() ? 0 : Integer.parseInt(num);
          }
      });
      

      这是一个测试:

      public static void main(String[] args) throws IOException {
          List<String> strings = Arrays.asList("room1.2", "foo1.1", "foo", "room2.3", "room100.999", "room10", "room.3");
      
          Collections.sort(strings, new Comparator<String>() {
              public int compare(String o1, String o2) {
                  return extractInt(o1) - extractInt(o2);
              }
      
              int extractInt(String s) {
                  String num = s.replaceAll("\\D", "");
                  // return 0 if no digits found
                  return num.isEmpty() ? 0 : Integer.parseInt(num);
              }
          });
          System.out.println(strings);
      }
      

      输出:

      [foo, room1, room2, room10, room100]
      

      当数字是小数时(也展示了 Java 8+ 风格):

      public static void main(String[] args) {
          List<String> strings = Arrays.asList("room1.2", "foo1.1", "room2.3", "room100.999", "room10", "room.3");
          Collections.sort(strings, Comparator.comparing(Application::extractDouble));
          System.out.println(strings);
      }
      
      static double extractDouble(String s) {
          String num = s.replaceAll("[^\\d.]", "");
          // return 0 if no digits found
          return num.isEmpty() ? 0 : Double.parseDouble(num);
      }
      

      结果:

      [foo, room.3, foo1.1, room1.2, room2.3, room10, room100.999]
      

      【讨论】:

      • 为什么我用 List strings = Arrays.asList("a", "aaa");结果不同于 List strings = Arrays.asList("aaa", "a"); ?我相信结果应该是一样的。请告诉我是否有错误...
      • @Bohemian 我怎样才能对这一行进行排序,但顺序如下: [room1, room2, room10, room100, foo] 第一个 - 反向字母 第二个 - 按数字顺序?
      • 这篇文章很老了,但是:@PonomarenkoOleh return num.isEmpty() ? 1 : Integer.parseInt(num);尝试 1 而不是 0。
      • 不适用于 Arrays.asList("1000HoVBSTest", "366MAC_CTX", "151TBD2");
      • @antnewbee 我添加了一个适用于小数的代码版本。
      【解决方案5】:

      一个懒惰的选择是让字符串比较器工作而不做任何额外的事情(定义你自己的比较器)。您可以通过用零填充字符串中的数字来实现这一点,如下所示:room0001, room0002, room0100 然后默认的字符串比较器将起作用。但是,您确实需要知道最大数值,以便相应地调整填充。

      【讨论】:

        【解决方案6】:

        使用@bohemian 答案。只是改善了一点。这对我很有效..

                Collections.sort(asdf, new Comparator<String>() {
                    public int compare(String o1, String o2) {
        
                        String o1StringPart = o1.replaceAll("\\d", "");
                        String o2StringPart = o2.replaceAll("\\d", "");
        
        
                        if(o1StringPart.equalsIgnoreCase(o2StringPart))
                        {
                            return extractInt(o1) - extractInt(o2);
                        }
                        return o1.compareTo(o2);
                    }
        
                    int extractInt(String s) {
                        String num = s.replaceAll("\\D", "");
                        // return 0 if no digits found
                        return num.isEmpty() ? 0 : Integer.parseInt(num);
                    }
                });
        

        【讨论】:

        • 在这种情况下,如果您有“q2ab”和“qa2b”,它们将是等价的,但它们不是。
        • 仅当要排序的内容有字符串前缀和整数后缀时才有效,但它符合我当前的需求。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-01
        • 1970-01-01
        • 2014-08-11
        • 1970-01-01
        • 2017-08-11
        • 2013-08-27
        • 2019-05-11
        相关资源
        最近更新 更多