比较版本标识符
时间:2020-03-05 18:43:56 来源:igfitidea点击:
这是我的代码,它采用" 1、5、0、4"或者" 1.5.0.4"形式的两个版本标识符,并确定哪个是较新的版本。
请提出建议或者改进!
/// <summary> /// Compares two specified version strings and returns an integer that /// indicates their relationship to one another in the sort order. /// </summary> /// <param name="strA">the first version</param> /// <param name="strB">the second version</param> /// <returns>less than zero if strA is less than strB, equal to zero if /// strA equals strB, and greater than zero if strA is greater than strB</returns> public static int CompareVersions(string strA, string strB) { char[] splitTokens = new char[] {'.', ','}; string[] strAsplit = strA.Split(splitTokens, StringSplitOptions.RemoveEmptyEntries); string[] strBsplit = strB.Split(splitTokens, StringSplitOptions.RemoveEmptyEntries); int[] versionA = new int[4]; int[] versionB = new int[4]; for (int i = 0; i < 4; i++) { versionA[i] = Convert.ToInt32(strAsplit[i]); versionB[i] = Convert.ToInt32(strBsplit[i]); } // now that we have parsed the input strings, compare them return RecursiveCompareArrays(versionA, versionB, 0); } /// <summary> /// Recursive function for comparing arrays, 0-index is highest priority /// </summary> private static int RecursiveCompareArrays(int[] versionA, int[] versionB, int idx) { if (versionA[idx] < versionB[idx]) return -1; else if (versionA[idx] > versionB[idx]) return 1; else { Debug.Assert(versionA[idx] == versionB[idx]); if (idx == versionA.Length - 1) return 0; else return RecursiveCompareArrays(versionA, versionB, idx + 1); } }
// @达伦·科普(Darren Kopp):
版本类不处理格式为1.0.0.5的版本。
解决方案
回答
好吧,由于我们只有四个元素的数组,因此我们可能只希望展开递归以节省时间。将数组作为参数传递将消耗内存,并留下一团糟供GC稍后清理。
回答
使用Version类。
Version a = new Version("1.0.0.0"); Version b = new Version("2.0.0.0"); Console.WriteLine(string.Format("Newer: {0}", (a > b) ? "a" : "b")); // prints b
回答
如果我们可以假设版本字符串中的每个位置仅是一个数字(或者至少是最后3个数字),则可以删除逗号或者句点并进行比较...这会快得多...不那么可靠,但是我们并不总是需要。
public static int CompareVersions(string strA, string strB) { char[] splitTokens = new char[] {'.', ','}; string[] strAsplit = strA.Split(splitTokens, StringSplitOptions.RemoveEmptyEntries); string[] strBsplit = strB.Split(splitTokens, StringSplitOptions.RemoveEmptyEntries); int versionA = 0; int versionB = 0; string vA = string.Empty; string vB = string.Empty; for (int i = 0; i < 4; i++) { vA += strAsplit[i]; vB += strBsplit[i]; versionA[i] = Convert.ToInt32(strAsplit[i]); versionB[i] = Convert.ToInt32(strBsplit[i]); } versionA = Convert.ToInt32(vA); versionB = Convert.ToInt32(vB); if(vA > vB) return 1; else if(vA < vB) return -1; else return 0; //they are equal }
是的,我在这里还假设有4个版本...
回答
System.Version类不支持带逗号的版本,因此Darren Kopp提供的解决方案是不够的。
这是一个尽可能简单的版本(但没有更简单)。
它使用System.Version,但通过在比较之前进行搜索替换来实现与版本号" 1、2、3、4"的兼容性。
/// <summary> /// Compare versions of form "1,2,3,4" or "1.2.3.4". Throws FormatException /// in case of invalid version. /// </summary> /// <param name="strA">the first version</param> /// <param name="strB">the second version</param> /// <returns>less than zero if strA is less than strB, equal to zero if /// strA equals strB, and greater than zero if strA is greater than strB</returns> public static int CompareVersions(String strA, String strB) { Version vA = new Version(strA.Replace(",", ".")); Version vB = new Version(strB.Replace(",", ".")); return vA.CompareTo(vB); }
该代码已经过测试:
static void Main(string[] args) { Test("1.0.0.0", "1.0.0.1", -1); Test("1.0.0.1", "1.0.0.0", 1); Test("1.0.0.0", "1.0.0.0", 0); Test("1, 0.0.0", "1.0.0.0", 0); Test("9, 5, 1, 44", "3.4.5.6", 1); Test("1, 5, 1, 44", "3.4.5.6", -1); Test("6,5,4,3", "6.5.4.3", 0); try { CompareVersions("2, 3, 4 - 4", "1,2,3,4"); Console.WriteLine("Exception should have been thrown"); } catch (FormatException e) { Console.WriteLine("Got exception as expected."); } Console.ReadLine(); } private static void Test(string lhs, string rhs, int expected) { int result = CompareVersions(lhs, rhs); Console.WriteLine("Test(\"" + lhs + "\", \"" + rhs + "\", " + expected + (result.Equals(expected) ? " succeeded." : " failed.")); }