2016-12-17 14 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

упаковка com.e;

импорт 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 Explorer, сортирует файлы :

enter image description here

I wrote a blog post about this. The 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; 
    } 
}