programing

분할 함수를 사용하지 않고 버전 번호 비교

javajsp 2023. 8. 22. 21:56

분할 함수를 사용하지 않고 버전 번호 비교

버전 번호를 비교하려면 어떻게 해야 합니까?

예를 들어:

x = 1.23.56.1487.5

y = 1.24.55.487.2

사용할 수 있습니까?Version수업?
https://learn.microsoft.com/en-us/dotnet/api/system.version

그것은 있습니다.IComparable인터페이스표시한 것처럼 5-part 버전 문자열에서는 작동하지 않습니다(실제 버전 문자열입니까?).입력이 문자열이라고 가정할 때, 여기 정상적인 작업 샘플이 있습니다.NET 4부 버전 문자열:

static class Program
{
    static void Main()
    {
        string v1 = "1.23.56.1487";
        string v2 = "1.24.55.487";

        var version1 = new Version(v1);
        var version2 = new Version(v2);

        var result = version1.CompareTo(version2);
        if (result > 0)
            Console.WriteLine("version1 is greater");
        else if (result < 0)
            Console.WriteLine("version2 is greater");
        else
            Console.WriteLine("versions are equal");
        return;

    }
}

소령.단조와 함께 살 수 있다면요.사용할 수 있는 build.build scheme.Net Version 클래스입니다.그렇지 않으면 왼쪽에서 오른쪽으로 어떤 종류의 구문 분석을 구현하고 차이점이 있거나 두 버전이 동일하다는 것을 반환할 때까지 계속해야 합니다.

@JohnD의 답변 외에도 분할('.') 또는 다른 문자열 <-> 변환 블롯을 사용하지 않고 부분 버전 번호만 비교해야 할 수 있습니다.나는 방금 1개의 추가 인수와 함께 확장 방법 CompareTo를 작성했습니다 - 비교할 버전 번호의 중요한 부분의 수(1과 4 사이).

public static class VersionExtensions
{
    public static int CompareTo(this Version version, Version otherVersion, int significantParts)
    {
        if(version == null)
        {
            throw new ArgumentNullException("version");
        }
        if(otherVersion == null)
        {
            return 1;
        }

        if(version.Major != otherVersion.Major && significantParts >= 1)
            if(version.Major > otherVersion.Major)
                return 1;
            else
                return -1;

        if(version.Minor != otherVersion.Minor && significantParts >= 2)
            if(version.Minor > otherVersion.Minor)
                return 1;
            else
                return -1;

        if(version.Build != otherVersion.Build && significantParts >= 3)
            if(version.Build > otherVersion.Build)
                return 1;
            else
                return -1;

        if(version.Revision != otherVersion.Revision && significantParts >= 4)
            if(version.Revision > otherVersion.Revision)
                return 1;
            else
                return -1;

        return 0; 
    }
}
public int compareVersion(string Version1,string Version2)
    {
        System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"([\d]+)");
        System.Text.RegularExpressions.MatchCollection m1 = regex.Matches(Version1);
        System.Text.RegularExpressions.MatchCollection m2 = regex.Matches(Version2);
        int min = Math.Min(m1.Count,m2.Count);
        for(int i=0; i<min;i++)
        {
            if(Convert.ToInt32(m1[i].Value)>Convert.ToInt32(m2[i].Value))
            {
                return 1;
            }
            if(Convert.ToInt32(m1[i].Value)<Convert.ToInt32(m2[i].Value))
            {
                return -1;
            }               
        }
        return 0;
    }

제 것은 여기 있어요."3.2.1.7650.b40"과 "3.10.1"과 같은 이상한 버전 문자열을 비교해야 했기 때문에 버전을 사용할 수 없었습니다.위에서 제안한 대로 정보 개체입니다.이것은 나에게 스타일을 주문하는 빠르고 더러운 것입니다.테스트할 수 있는 짧은 기능도 제공했습니다.

using System;
                    
public class Program
{
    public static void Main()
    {
        Test_CompareVersionStrings();
    }
    
    /// <summary>
    /// Compare two version strings, e.g.  "3.2.1.0.b40" and "3.10.1.a".
    /// V1 and V2 can have different number of components.
    /// Components must be delimited by dot.
    /// </summary>
    /// <remarks>
    /// This doesn't do any null/empty checks so please don't pass dumb parameters
    /// </remarks>
    /// <param name="v1"></param>
    /// <param name="v2"></param>
    /// <returns>
    /// -1 if v1 is lower version number than v2,
    /// 0 if v1 == v2,
    /// 1 if v1 is higher version number than v2,
    /// -1000 if we couldn't figure it out (something went wrong)
    /// </returns>
    private static int CompareVersionStrings(string v1, string v2)
    {
        int rc = -1000;

        v1 = v1.ToLower();
        v2 = v2.ToLower();

        if (v1 == v2)
            return 0;

        string[] v1parts = v1.Split('.');
        string[] v2parts = v2.Split('.');

        for (int i = 0; i < v1parts.Length; i++)
        {
            if (v2parts.Length < i+1)
                break; // we're done here
            
            string v1Token = v1parts[i];
            string v2Token = v2parts[i];
            
            int x;
            bool v1Numeric = int.TryParse(v1Token, out x);
            bool v2Numeric = int.TryParse(v2Token, out x);
            
            // handle scenario {"2" versus "20"} by prepending zeroes, e.g. it would become {"02" versus "20"}
            if (v1Numeric && v2Numeric) {
                while (v1Token.Length < v2Token.Length)
                    v1Token = "0" + v1Token;
                while (v2Token.Length < v1Token.Length)
                    v2Token = "0" + v2Token;
            }

            rc = String.Compare(v1Token, v2Token, StringComparison.Ordinal);
            //Console.WriteLine("v1Token=" + v1Token + " v2Token=" + v2Token + " rc=" + rc);
            if (rc != 0)
                break;
        }

        if (rc == 0)
        {
            // catch this scenario: v1="1.0.1" v2="1.0"
            if (v1parts.Length > v2parts.Length)
                rc = 1; // v1 is higher version than v2
            // catch this scenario: v1="1.0" v2="1.0.1"
            else if (v2parts.Length > v1parts.Length)
                rc = -1; // v1 is lower version than v2
        }

        if (rc == 0 || rc == -1000)
            return rc;
        else
            return rc < 0 ? -1 : 1;
    }
    
    private static int _CompareVersionStrings(string v1, string v2)
    {
        int rc = CompareVersionStrings(v1, v2);
        Console.WriteLine("Compare v1: " + v1 + "  v2: " + v2 + "  result: " + rc);
        return rc;
    }

    // for debugging
    private static void Test_CompareVersionStrings()
    {
        bool allPass = true;

        // should be equal
        allPass &= (0 == _CompareVersionStrings("1", "1"));
        allPass &= (0 == _CompareVersionStrings("1.1", "1.1"));
        allPass &= (0 == _CompareVersionStrings("3.3.a20", "3.3.A20"));

        // v1 should be lower
        allPass &= (-1 == _CompareVersionStrings("1", "2"));
        allPass &= (-1 == _CompareVersionStrings("1.0", "1.0.1"));
        allPass &= (-1 == _CompareVersionStrings("1.0", "1.1"));
        allPass &= (-1 == _CompareVersionStrings("1.0.0.3", "1.1"));
        allPass &= (-1 == _CompareVersionStrings("1.2.3.4", "1.2.3.4b"));
        allPass &= (-1 == _CompareVersionStrings("1.2.3.4", "1.2.3.4.b"));
        allPass &= (-1 == _CompareVersionStrings("1.8.0", "20.0.0.0"));
        allPass &= (-1 == _CompareVersionStrings("5.6.0.788.2", "20.0.0.0"));

        // v1 should be higher
        allPass &= (1 == _CompareVersionStrings("2", "1"));
        allPass &= (1 == _CompareVersionStrings("1.0.1", "1.0"));
        allPass &= (1 == _CompareVersionStrings("1.1", "1.0"));
        allPass &= (1 == _CompareVersionStrings("1.1", "1.0.0.3"));
        allPass &= (1 == _CompareVersionStrings("1.2.3.4b", "1.2.3.4"));
        allPass &= (1 == _CompareVersionStrings("1.2.3.4.b", "1.2.3.4")); 
        allPass &= (1 == _CompareVersionStrings("20.0.0.0", "5.6.0.788.2"));

        Console.WriteLine("allPass = " + allPass.ToString());
    }   
}

어떤 이유로 버전의 비교 방법을 직접 사용할 수 없는 경우(예: 클라이언트-서버 시나리오) 다른 방법은 버전에서 긴 숫자를 추출한 다음 서로 비교하는 것입니다.그러나 번호 형식은 다음과 같아야 합니다.메이저, 마이너 및 리비전의 경우 두 자리, 빌드의 경우 네 자리입니다.

버전 번호를 추출하는 방법:

var version = Assembly.GetExecutingAssembly().GetName().Version;

long newVersion = version.Major * 1000000000L + 
                   version.Minor * 1000000L + 
                   version.Build * 1000L + 
                   version.Revision;

그리고 다른 곳에서 비교할 수 있습니다.

if(newVersion > installedVersion)
{
  //update code
}

참고: installedVersion은 이전에 추출된 긴 숫자입니다.

인터넷에서 이 알고리즘이 잘 작동하는 것 같습니다.

//https://www.geeksforgeeks.org/compare-two-version-numbers/amp/

static int versionCompare(string v1, string v2)
    {
        // vnum stores each numeric
    
        // part of version
    
        int vnum1 = 0, vnum2 = 0;
    
        // loop until both string are
        // processed
    
        for (int i = 0, j = 0; (i < v1.Length || j < v2.Length);)
    
        {
            // storing numeric part of
            // version 1 in vnum1
            while (i < v1.Length && v1[i] != '.')
            {
    
                vnum1 = vnum1 * 10 + (v1[i] - '0');
    
                i++;
            }
            // storing numeric part of
    
            // version 2 in vnum2
    
            while (j < v2.Length && v2[j] != '.')
            {
                vnum2 = vnum2 * 10 + (v2[j] - '0');
                j++;
            }
            if (vnum1 > vnum2)
                return 1;
    
            if (vnum2 > vnum1)
                return -1;
    
            // if equal, reset variables and
    
            // go for next numeric part
            vnum1 = vnum2 = 0;
            i++;
            j++;
        }
    
        return 0;
    
    }

언급URL : https://stackoverflow.com/questions/7568147/compare-version-numbers-without-using-split-function