我的下面的代码应该将版本号排序为正确的顺序。在大多数情况下它可以工作,但它失败了一个我无法访问的隐藏测试用例。鉴于有任何边缘情况,你可以看到我可能会失踪。
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 :(得分:1)
我最近需要以更通用的方式为任意文件名执行此操作,类似于Windows资源管理器对文件进行排序的方式:
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;
}
}
答案 1 :(得分:1)
我在Lukas Eder's blog post中阅读了comment above,并创建了一个java.util.Comparator
,该import java.util.ArrayList;
import java.util.List;
public class JavaTest {
public static void main(String[] args) {
final List<String> chapters = new ArrayList<>();
chapters.add("1.1");
chapters.add("1.2");
chapters.add("1");
chapters.add("1.3");
chapters.add("1.1.1");
chapters.add("5.6");
chapters.add("1.1.10");
chapters.add("4");
chapters.add("1.1.9");
chapters.add("1.2.1.10");
chapters.add("2.1.1.4.5");
chapters.add("1.2.1.9");
chapters.add("1.2.1");
chapters.add("2.2.2");
chapters.add("1.2.1.11");
System.out.println("UNSORTED: " + chapters.toString());
chapters.sort(VersionNumberComparator.getInstance());
System.out.println("SORTED: " + chapters.toString());
}
}
根据JDK proposal按版本(或章节)编号排序。
VersionNumberComparator
是在GitHub要点中定义的。以下代码显示了它的工作原理。
UNSORTED: [1.1, 1.2, 1, 1.3, 1.1.1, 5.6, 1.1.10, 4, 1.1.9, 1.2.1.10, 2.1.1.4.5, 1.2.1.9, 1.2.1, 2.2.2, 1.2.1.11]
SORTED: [1, 1.1, 1.1.1, 1.1.9, 1.1.10, 1.2, 1.2.1, 1.2.1.9, 1.2.1.10, 1.2.1.11, 1.3, 2.1.1.4.5, 2.2.2, 4, 5.6]
产生以下输出:
{{1}}
答案 2 :(得分: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;
}
答案 3 :(得分:0)
包com.e;
import java.util。*;
/ ** *由dpc于17-2-27创建。 * * / 公共类VersionComparator实现Comparator {
@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));
}
}