【问题标题】:Sort String with possible numbers in it使用可能的数字对字符串进行排序
【发布时间】:2014-07-09 12:54:07
【问题描述】:

我有以下可能的地址作为字符串(未排序):

"road 21"
"road 1"
"road 186"
"road +21 / 23"
"road +21 / 19"
"another road 21"
"another road 1"

并且我希望能够将它们排序为(所以不是默认的字符串排序方式):

another road 1
another road 21
road 1
road 21
road +21 / 19
road +21 / 23
road 186

我该怎么做?我可能必须使用自定义比较器,但我应该如何拆分字符串?

【问题讨论】:

  • 我认为road 186 会出现在road +21 / 19 之前。除非您将 + 计为数字 21 的一部分(换句话说,忽略它,因为它不会影响数字)。
  • road 186 应该在 +21 之前,我确实忽略了 +。这只是他们有时在这里使用的一种格式。 @user902383:我知道存在正则表达式的拆分,但实际上我不知道如何为这部分编写正则表达式:)。

标签: java string sorting


【解决方案1】:

我用 Java 实现了这个,我知道它一开始看起来很奇怪。

如果你有任何问题,请随时问我

public class SpecialComparator implements Comparator<String> {

   @Override
    public int compare(String arg0, String arg1) {
     // TODO Auto-generated method stub
     String []words1=arg0.split(" ");
     String [] words2 = arg1.split(" ");
     int i = 0;

        if (words1[i].hashCode()>words2[i].hashCode()){
            return 1;
        }
        else if (words1[i].hashCode()<words2[i].hashCode()){
            return -1;
        }
        else if (words1[i].hashCode()==words2[i].hashCode())
            return compare(arg0.substring(i+1, arg0.length()), arg1.substring(i+1,arg1.length()));
        else if (i == Math.min(words1.length,words2.length)-1 && Math.min(words1.length,words2.length) == words1.length){
            return -1;
        }
        else if (i == Math.min(words1.length,words2.length)-1 && Math.min(words1.length,words2.length) == words2.length){
            return 1;
        }
        else if (i == Math.min(words1.length,words2.length)-1 && words1.length == words2.length){
            return 0;
        }
        else{
            return 0;
        }


   }


   public static void main (String[] args){
    ArrayList<String> input = new ArrayList<String>();
    SpecialComparator a = new SpecialComparator();
    input.add("road 21");
    input.add("road 1");
    input.add("road 186");
    input.add("road +21 / 23");
    input.add("road +21 / 19");
    input.add("another road 21");
    input.add("another road 1");
    Collections.sort(input,a);
    for (String ans : input){
        System.out.println(ans);
    }

  }



 }

【讨论】:

  • 这对我的情况进行了 100% 的完美排序。谢谢!我正在更改“NaturalOrderComparator”实现,但由于这是有效的,我正在使用您的代码。谢谢
  • 这个练习很有趣。
【解决方案2】:

您的格式似乎是:

  • {姓名}
  • {编号}
  • 可选斜杠字符
  • 可选的第二个 {number}。

因此,我将使用这些属性创建一个表示此格式的对象:

public class MyInput {
  private String name;
  private Integer firstNumber;
  private Integer secondNumber;
}

然后解析您的输入文件以创建List&lt;MyInput&gt;

最后,你创建一个自定义的Comparator可以调用Collections.sort(yourList, yourCustomComparator)

【讨论】:

    【解决方案3】:

    这个问题似乎经常出现。我一直在使用 Martin Pools NaturalOrderCompartor。您可以轻松地将其移植到您的代码中。

    https://github.com/paour/natorder/blob/master/NaturalOrderComparator.java

    【讨论】:

    • 没有完美排序,但它几乎就在那里。猜测在很多情况下都可以。
    【解决方案4】:

    这有点讨厌,但这是我为您解决问题的方法

    List<String> list = Arrays.asList("road 21", "road 1", "road 186",
                    "road +21 / 23", "road +21 / 19", "another road 21",
                    "another road 1");
    
            Collections.sort(list, new Comparator<String>() {
    
                Integer toNumber(String string) {
                    try {
                        return Integer.parseInt(string);
                    } catch (NumberFormatException e) {
                        return null;
                    }
                }
    
                @Override
                public int compare(String o1, String o2) {
                    String[] left = o1.split("\\s+");
                    String[] right = o2.split("\\s+");
                    for (int i = 0; i < Math.min(left.length, right.length); i++) {
                        String ls = left[i];
                        String rs = right[i];
    
                        Integer li = toNumber(ls);
                        Integer ri = toNumber(rs);
    
                        if (li != null && ri != null
                                && li.intValue() != ri.intValue()) {
                            return li.intValue() - ri.intValue();
                        } else if (li != null && ri == null) {
                            return 1;
                        } else if (li == null && ri != null) {
                            return -1;
                        } else if (li == null && ri == null){
                            int compared = ls.compareToIgnoreCase(rs);
                            if (compared != 0) {
                                return compared;
                            }
                        }
    
                    }
                    return left.length - right.length;
                }
            });
    

    但如果您可以更改结构,请使用 Arnaud Denoyelle 提出的解决方案

    【讨论】:

    • 我实际上无法更改结构。否则我可能更喜欢他的解决方案。
    【解决方案5】:

    您也可以尝试以下比较器:

    class MyComparator implements Comparator<String> {
    
        @Override
        public int compare(String o1, String o2) {
            o1 = o1.replace("+", "");
            o2 = o2.replace("+", "");
    
            String[] a1 = o1.split(" ");
            String[] a2 = o2.split(" ");
            int length = (a1.length > a2.length) ? a2.length : a1.length;
    
            for (int i = 0; i < length; i++) {
                if (!a1[i].equalsIgnoreCase(a2[i])) {
                    if (!isIntegerRegex(a1[i]) || !isIntegerRegex(a2[i])) {
                        return o1.compareTo(o2);
                    }
                    int f = Integer.parseInt(a1[i]);
                    int s = Integer.parseInt(a2[i]);
                    return f - s;
                }
            }
    
            return a1.length - a2.length;
        }
    
        public boolean isIntegerRegex(String str) {
            return str.matches("^[0-9]+$");
        }
    }
    

    并称它为:

    public String[] sortStrings(String[] input) {
        Arrays.sort(input, new MyComparator());
        return input;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-07
      • 2021-03-17
      相关资源
      最近更新 更多