多部分字母数字字符串的比较

时间:2013-09-06 13:11:21

标签: c# string comparison

我收到一个字符串,其中包含当前在系统中运行的sw版本。

我想只在系统运行某个sw版本时才进行一些操作 后面。

e.g。如果系统正在运行sw版本2.D或更高版本(2.E,..),我会执行一些操作。如果系统运行较低的sw版本(2.C,..),那么我不这样做。

如何对字符串进行比较?

2 个答案:

答案 0 :(得分:0)

有很多方法可以做到这一点,但是如果你知道字符串的格式是x.y甚至是x.y.z ......那么我建议使用自定义StringComparer:

using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace StingComparisons
{
[TestClass]
public class StringComparison
{
    [TestMethod]
    public void TestMethod1()
    {
        var a = "2.E";
        var b = "2.F";
        var c = "2.C";
        var d = "1.F";
        var e = "3.A";

        StringComparer comp = new MyStringComparer();

        Assert.IsTrue(b.IsSameOrAfter(a, comp));
        Assert.IsFalse(c.IsSameOrAfter(a, comp));
        Assert.IsFalse(d.IsSameOrAfter(a, comp));
        Assert.IsTrue(e.IsSameOrAfter(a, comp));
        Assert.IsTrue(a.IsSameOrAfter(a, comp));
    }

    [TestMethod]
    public void TestMethod2()
    {
        var a = "2.E.1";
        var b = "2.E";
        var c = "2.E.2";
        var d = "2.F";
        var e = "2.D.3";
        var f = "3.A";

        StringComparer comp = new MyStringComparer();

        Assert.IsFalse(b.DotDelimitedIsSameOrAfter(a));
        Assert.IsTrue(c.DotDelimitedIsSameOrAfter(a));
        Assert.IsTrue(d.DotDelimitedIsSameOrAfter(a));
        Assert.IsFalse(e.DotDelimitedIsSameOrAfter(a));
        Assert.IsTrue(f.DotDelimitedIsSameOrAfter(a));
        Assert.IsTrue(a.DotDelimitedIsSameOrAfter(a));
    }
}

public static class stringExtensions
{
            public static bool DotDelimitedIsSameOrAfter(this string a, string b)
            {
                   return a.IsSameOrAfter(b, new MyStringComparer());
            }

    public static bool IsSameOrAfter(this string a, string b, StringComparer comp)
    {
        return comp.Compare(a, b) <= 0;
    }
}

public class MyStringComparer : StringComparer
{

    public override int Compare(string x, string y)
    {
        var partsX = x.Split('.');
        var partsY = y.Split('.');
        for (int i = 0; i < partsY.Length; i++)
        {
            if (partsX.Length <= i)
                return 1;
            var partComp = partsY[i].CompareTo(partsX[i]);
            if (partComp != 0)
                return partComp;
        }
        return 0;
    }

    public override bool Equals(string x, string y)
    {
        return x.Equals(y);
    }

    public override int GetHashCode(string obj)
    {
        return obj.GetHashCode();
    }
}
}

我将调用包装在一个扩展方法中纯粹是为了让它更具可读性。

答案 1 :(得分:0)

由于我只需要(以及更多),我编写了以下比较器,它比较了两个字母数字版本字符串:

/// <summary>
/// Compares two alphanumeric version numbers.
/// </summary>
public class AlphanumericVersionComparer : IComparer<string>
{
    /// <summary>
    /// Compares two alphanumeric version numbers and returns a value
    /// indicating whether one is less than, equal to, or greater than the other.
    /// </summary>
    /// <param name="x">The first alphanumeric version number to compare.</param>
    /// <param name="y">The second alphanumeric version number to compare.</param>
    /// <returns>A signed integer that indicates the relative values of x and y.</returns>
    public int Compare(string x, string y)
    {
        // Validate parameters
        if (x == null) throw new ArgumentNullException("x");
        if (y == null) throw new ArgumentNullException("y");

        // Test for equality
        if (x == y)
            return 0;

        // Split the different parts of the number
        string[] xParts = x.Split('.');
        string[] yParts = y.Split('.');

        // Compare each parts
        AlphanumericComparer alphaNumComparer = new AlphanumericComparer();
        for (int i = 0, n = Math.Max(xParts.Length, yParts.Length); i < n; i++)
        {
            // If the part at index i is not in y => x is greater
            if (i >= yParts.Length)
                return 1;

            // If the part at index i is not in x => y is greater
            if (i >= xParts.Length)
                return -1;

            // Compare the two alphanumerical numbers
            int result = alphaNumComparer.Compare(xParts[i], yParts[i]);
            if (result != 0)
            {
                return result;
            }
        }

        // The two numbers are equal (really??? I thought we tested for equality already!)
        System.Diagnostics.Debug.Fail("Not supposed to reach this code...");
        return 0;
    }
}

/// <summary>
/// Compares two alphanumeric strings.
/// </summary>
/// <remarks>See http://snipd.net/alphanumericnatural-sorting-in-c-using-icomparer </remarks>
public class AlphanumericComparer : IComparer<string>
{
    /// <summary>
    /// Compares two alphanumerics and returns a value
    /// indicating whether one is less than, equal to, or greater than the other.
    /// </summary>
    /// <param name="x">The first alphanumeric to compare.</param>
    /// <param name="y">The second alphanumeric to compare.</param>
    /// <returns>A signed integer that indicates the relative values of x and y.</returns>
    public int Compare(string x, string y)
    {
        int len1 = x.Length;
        int len2 = y.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = x[marker1];
            char ch2 = y[marker2];

            // Some buffers we can build up characters in for each chunk.
            char[] space1 = new char[len1];
            int loc1 = 0;
            char[] space2 = new char[len2];
            int loc2 = 0;

            // Walk through all following characters that are digits or
            // characters in BOTH strings starting at the appropriate marker.
            // Collect char arrays.
            do
            {
                space1[loc1++] = ch1;
                marker1++;

                if (marker1 < len1)
                {
                    ch1 = x[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

            do
            {
                space2[loc2++] = ch2;
                marker2++;

                if (marker2 < len2)
                {
                    ch2 = y[marker2];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));

            // If we have collected numbers, compare them numerically.
            // Otherwise, if we have strings, compare them alphabetically.
            string str1 = new string(space1);
            string str2 = new string(space2);

            int result;

            if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
            {
                int thisNumericChunk = int.Parse(str1);
                int thatNumericChunk = int.Parse(str2);
                result = thisNumericChunk.CompareTo(thatNumericChunk);
            }
            else
            {
                result = str1.CompareTo(str2);
            }

            if (result != 0)
            {
                return result;
            }
        }
        return len1 - len2;
    }
}

你可以在这里玩小提琴:https://dotnetfiddle.net/28iius

http://snipd.net/alphanumericnatural-sorting-in-c-using-icomparer的所有积分用于字母数字比较。