2008-08-27 9 views
25

Вот мой код, который принимает два идентификатора версии в форме «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.

+0

Извините, но последнее предложение позвольте мне интересно, если что-то (что?) Должно быть неправильно с классом System.Version? Что особенного в «1.0.0.5». В принятом ответе также используется класс Version. Или вы имели в виду «.. не обрабатывают [..]« 1,0,0,5 »? – Philm 2014-04-24 21:08:31

ответ

29

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.")); 
    } 
+0

Искал такого рода вещи, никогда не видел класс `Version` раньше, спасибо! – b729sefc 2014-07-03 20:07:25

1

Ну, так как у вас есть только четыре элемента массива, вы можете просто захотеть развернуть рекурсию, чтобы сэкономить время. Передача массивов в качестве аргументов будет поглощать память и оставлять беспорядок для GC для очистки позже.

38

Используйте класс 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 
+0

Спасибо за это! Это лучшее решение для меня, потому что сравнение корректно работает с любым количеством цифр версии, например, Версия («12.4.5.0»)> Версия («3.4.5.0»). – dbeachy1 2015-03-03 05:03:50

0

Если вы можете предположить, что каждое место в строке версии будет только один номер (или, по крайней мере последние 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 версии места здесь ...

+1

, если каждое место имеет только одну цифру, просто замените «,» на «.», А затем сравните версии как строку. Это намного проще, чем ваш код – 2012-04-16 04:23:18