2008-08-27 5 views
25

「1,5,0,4」または「1.5.0.4」という2つのバージョン識別子を使用し、どちらが新しいバージョンであるかを判断するコードです。バージョン識別子を比較します

提案や改善をお願いします。

Darren Kopp @
/// <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); 
     } 
    } 

クラスはフォーマット1.0.0.5のバージョンに対応していないバージョン。

+0

申し訳ありませんが、最後の文は、何かが(何を?)System.Versionクラスと間違っている必要がある場合、私は、不思議聞かせて? "1.0.0.5"には特別なものがあります。受け入れられる答えはVersionクラスも使用します。または、あなたは ".. do not do handle .." 1,0,0,5 "? – Philm

答えて

29

を4つのバージョンの場所を想定していますカンマが入っているため、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

+0

バージョン番号に2桁の数字が含まれているとどうなりますか?' Test( "12.3.4.5"、 "2.0.0.0" 1); '?" 2 ">" 1 "なので、文字列の比較結果が間違っていませんか? – dbeachy1

1

あなたは4要素の配列しか持たないので、時間を節約するために再帰をアンロールしたくないかもしれません。引数として配列を渡すとメモリーが枯渇し、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

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 
} 

そして、はい、私もSystem.Versionクラスが持つバージョンはサポートしていません...ここ

+1

各桁に数字が1つしかない場合は、 "、"を "。"に置き換えてバージョンを文字列として比較します。コード。 –