2016-12-17 62 views
1

下面的代码应该按照正确的顺序对版本号进行排序。它的大部分工作原理,但它没有一个我无法访问的隐藏的测试用例。鉴于有任何边缘情况,你可以看到我可能会失踪。排序版本号

import java.util.*; 

public class Answer { 
public static void main(String[] args) 
{ 
    //Testing 
    String[] versions = {"0.0.0","0","0.0","1.113","0.0.0.1","2.0.0","1.2","2","0.1","1.2.1","1.1.1","2.0"}; 
    String[] results = answer(versions); 
    for(int i =0; i<results.length;i++) 
    { 
     System.out.println(results[i]); 
    } 
} 
public static String[] answer(String[] l) { 

    String temp = new String(); 
    //Insertion sort on the given array to assign correct version numbers 
    for (int i = 1; i < l.length; i++) { 
     for(int j = i ; j > 0 ; j--){ 
      if(compareVersion(l[j],l[j-1])<0){ 
       temp = l[j]; 
       l[j] = l[j-1]; 
       l[j-1] = temp; 
      } 
     } 
    } 
    return l; 
} 
//Will compare version numbers breaking it apart into a String array 
public static int compareVersion(String version1, String version2) { 
String[] arr1 = version1.split("\\."); 
String[] arr2 = version2.split("\\."); 

int i=0; 
while(i<arr1.length || i<arr2.length){ 
    if(i<arr1.length && i<arr2.length){ 
     if(Integer.parseInt(arr1[i]) < Integer.parseInt(arr2[i])){ 
      return -1; 
     }else if(Integer.parseInt(arr1[i]) > Integer.parseInt(arr2[i])){ 
      return 1; 
     } 
     else if(Integer.parseInt(arr1[i]) == Integer.parseInt(arr2[i])) 
     { 
      int result = specialCompare(version1,version2); 
      if(result != 0) 
      { 
       return result; 
      } 
     } 
    } else if(i<arr1.length){ 
     if(Integer.parseInt(arr1[i]) != 0){ 
      return 1; 
     } 
    } else if(i<arr2.length){ 
     if(Integer.parseInt(arr2[i]) != 0){ 
      return -1; 
     } 
    } 

    i++; 
} 

return 0; 
} 
    // Meant for when version numbers such as 2 and 2.0 arise. This method will make sure to 
    // put the smaller version number (in length) first 
    public static int specialCompare(String str1, String str2) 
{ 
     String[] arr1 = str1.split("\\."); 
    String[] arr2 = str2.split("\\."); 
    for(int i =1; i<arr1.length;i++) 
    { 
     if(Integer.parseInt(arr1[i]) != 0) 
     { 
      return 0; 
     } 
    } 
    for(int j =1; j<arr2.length;j++) 
    { 
     if(Integer.parseInt(arr2[j]) != 0) 
     { 
      return 0; 
     } 
    } 
    if(arr1.length < arr2.length) 
    { 
     return -1; 
    } 
    else 
    { 
     return 1; 
    } 

} 
} 
+0

您希望有人在您的代码中修复某些内容,但您甚至不知道失败是什么?你认为任何人都可以完成这个任务?看看http://stackoverflow.com/help/how-to-ask并试图澄清你的问题 – pvg

回答

0

在你的代码上述specialCompare方法您的意见...

意味着当版本号,如2和2.0出现。这种方法 将确保把较小的版本号(长)第一

所以我从这个您想要的版本通过版本号的长度进行排序猜测。例如:从您提供的版本字符串数组要如下排序​​...

0 
2 
0.0 
0.1 
1.2 
1.113 
2.0 
0.0.0 
1.1.1 
1.2.1 
2.0.0 
0.0.0.1 

如果是这样的话,那么你似乎使这个复杂得多,它必须是。当你得到版本长度不同的两个版本时,应该先选择版本长度较短的版本。因此,简单检查版本拆分数组的长度应该解决这个问题。如果它们长度相同,则需要检查每个版本。当版本长度相同时,不需要使用specialCompare方法。只需检查每个版本以及它们是否相同,然后转到下一个版本号等等。只要一个版本不同,你就会知道要返回什么。如果你经历了整个阵列,那么你知道所有的版本号都是一样的。

下面是使用上述逻辑对compareVersion方法的更改。没有必要使用specialCompare方法。我猜这是你正在寻找的。

public static int compareVersion(String version1, String version2) 
{ 
    String[] arr1 = version1.split("\\."); 
    String[] arr2 = version2.split("\\."); 

    if (arr1.length < arr2.length) 
    return -1; 
    if (arr1.length > arr2.length) 
    return 1; 

    // same number of version "." dots 
    for (int i = 0; i < arr1.length; i++) 
    { 
    if(Integer.parseInt(arr1[i]) < Integer.parseInt(arr2[i])) 
     return -1; 
    if(Integer.parseInt(arr1[i]) > Integer.parseInt(arr2[i])) 
     return 1; 
    } 
    // went through all version numbers and they are all the same 
    return 0; 
} 
+0

是的,事实证明,我在今天早上就明白了这一点,并且让自己变得更加困难。但我很感谢你回答我的问题。 –

0

package com.e;

import java.util。*;

/** *由dpc在17-2-27创建。 * */ 公共类VersionComparator实现比较{

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

    if (o1 == null && o2 == null) { 
     return 0; 
    } else if (o1 == null && o2 != null) { 
     return -1; 
    } else if (o1 != null && o2 == null) { 
     return 1; 
    } else { 
     if (o1.length() == 0 && o2.length() == 0) { 
      return 0; 
     } else if (o1.length() == 0 && o2.length() > 0) { 
      return -1; 
     } else if (o1.length() > 0 && o2.length() == 0) { 
      return 1; 
     } else { 
      return compareVersion(o1, o2); 
     } 
    } 


} 


public static int compareVersion(String version1, String version2) { 
    String[] arr1 = version1.split("\\."); 
    String[] arr2 = version2.split("\\."); 

    try { 

     int i = 0; 
     while (i < arr1.length || i < arr2.length) { 
      if (i < arr1.length && i < arr2.length) { 
       if (Integer.parseInt(arr1[i]) < Integer.parseInt(arr2[i])) { 
        return -1; 
       } else if (Integer.parseInt(arr1[i]) > Integer.parseInt(arr2[i])) { 
        return 1; 
       } else if (Integer.parseInt(arr1[i]) == Integer.parseInt(arr2[i])) { 
        int result = specialCompare(version1, version2); 
        if (result != 0) { 
         return result; 
        } 
       } 
      } else if (i < arr1.length) { 
       if (Integer.parseInt(arr1[i]) != 0) { 
        return 1; 
       } 
      } else if (i < arr2.length) { 
       if (Integer.parseInt(arr2[i]) != 0) { 
        return -1; 
       } 
      } 

      i++; 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return 0; 
} 

public static int specialCompare(String str1, String str2) { 
    String[] arr1 = str1.split("\\."); 
    String[] arr2 = str2.split("\\."); 
    for (int i = 1; i < arr1.length; i++) { 
     if (Integer.parseInt(arr1[i]) != 0) { 
      return 0; 
     } 
    } 
    for (int j = 1; j < arr2.length; j++) { 
     if (Integer.parseInt(arr2[j]) != 0) { 
      return 0; 
     } 
    } 
    if (arr1.length < arr2.length) { 
     return -1; 
    } else { 
     return 1; 
    } 
} 


// test 
public static List<String> getLowerList(String str, Comparator<String> comparator, List<String> list) { 
    if (str == null) { 
     return list; 
    } 
    List<String> newlist = new ArrayList<String>(); 
    newlist.add(str); 
    newlist.addAll(list); 
    // sort 
    Collections.sort(newlist, comparator); 
    // search 
    int endIndex = Collections.binarySearch(newlist, str); 
    if (endIndex >= 0) { 
     // sublist 0 1 
     return newlist.subList(0, endIndex + 1); 
    } else { 
     return new ArrayList<String>(); 
    } 
} 

public static void main(String[] args) { 
    List<String> test1 = Arrays.asList(new String[]{ 
      "2.1.1", "1.21.22", "1.21.25", "1.113", "0.0.0.1", 
      "2.0.0", "1.2", "2.0", "0.1", "1.2.1", "1.1.1", 
      "11", "100", "" + Integer.MAX_VALUE + ".1", "", 
      "2.0", "10.1"}); 

    List<String> test2 = Arrays.asList(new String[]{"", null, "0", "10.20.100", "3.1.1", "9.8", "10.3.92"}); 

    List<String> newlist = new ArrayList<String>(); 
    newlist.addAll(test1); 
    newlist.addAll(test2); 

    Collections.sort(newlist, new VersionComparator()); 

    VersionComparator compareVersion = new VersionComparator(); 
    System.out.println(newlist); 

    System.out.println(getLowerList("2", compareVersion, newlist)); 
    System.out.println(getLowerList("3", compareVersion, newlist)); 
    System.out.println(getLowerList("4", compareVersion, newlist)); 
    System.out.println(getLowerList("5", compareVersion, newlist)); 

} 

}

0

我最近有需要的任意文件名这样做是一个更通用的方法,类似于Windows资源管理器如何排序文件:

enter image description here

I wrote a blog post about thisThe idea was inspired by this answer here。以这种方式订购文件的比较器如下所示:

public final class FilenameComparator implements Comparator<String> { 
    private static final Pattern NUMBERS = 
     Pattern.compile("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"); 
    @Override public final int compare(String o1, String o2) { 
     // Optional "NULLS LAST" semantics: 
     if (o1 == null || o2 == null) 
      return o1 == null ? o2 == null ? 0 : -1 : 1; 

     // Splitting both input strings by the above patterns 
     String[] split1 = NUMBERS.split(o1); 
     String[] split2 = NUMBERS.split(o2); 
     for (int i = 0; i < Math.min(split1.length, split2.length); i++) { 
      char c1 = split1[i].charAt(0); 
      char c2 = split2[i].charAt(0); 
      int cmp = 0; 

      // If both segments start with a digit, sort them numerically using 
      // BigInteger to stay safe 
      if (c1 >= '0' && c1 <= '9' && c2 >= 0 && c2 <= '9') 
       cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i])); 

      // If we haven't sorted numerically before, or if numeric sorting yielded 
      // equality (e.g 007 and 7) then sort lexicographically 
      if (cmp == 0) 
       cmp = split1[i].compareTo(split2[i]); 

      // Abort once some prefix has unequal ordering 
      if (cmp != 0) 
       return cmp; 
     } 

     // If we reach this, then both strings have equally ordered prefixes, but 
     // maybe one string is longer than the other (i.e. has more segments) 
     return split1.length - split2.length; 
    } 
}