当“两侧”都为数字时,如何将字母数字值排序为数字是数字吗?

发布于 2024-12-20 04:00:48 字数 116 浏览 0 评论 0原文

我们在网格中有一些列包含数字、字符串或以数字开头的字符串,用户希望它们以合理的方式排序。 (格式取决于客户,因此我们不知道字符串的格式)

是否有 IComparable 的预封装实现可以执行类似的操作?

We have some columns in a grid that contain numbers, strings, or strings that start with a number and the users expect them to sort in a sensible way. (The format depends on the customer so we don’t know the formats the strings will be in)

Is there a pre-canned” implementation of IComparable that does something like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把人绕傻吧 2024-12-27 04:00:48

这是一个快速的字母数字排序(也可用于其他数字排序)。

C# 字母数字排序 http://www.dotnetperls.com/alphanumeric-sorting

var unordered = new[] { "100F", "50F", "SR100", "SR9" };
var ordered = unordered.OrderBy(s => s, new AlphanumComparatorFast());

这是一个关于这个问题的好文章:

Sorting for Humans : Natural Sort Order http://www.codinghorror.com/ blog/2007/12/sorting-for- humans-natural-sort-order.html

这是 AlphanumComparatorFast 类,以防上述链接停止工作页面指​​出“它可以在任何程序中使用,没有任何限制”,并且代码开头的注释也表明它可以免费使用:

// NOTE: This code is free to use in any program.
// ... It was developed by Dot Net Perls.

public class AlphanumComparatorFast : IComparer
{
    public int Compare(object x, object y)
    {
        string s1 = x as string;
        if (s1 == null)
        {
            return 0;
        }
        string s2 = y as string;
        if (s2 == null)
        {
            return 0;
        }

        int len1 = s1.Length;
        int len2 = s2.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = s1[marker1];
            char ch2 = s2[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 = s1[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

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

                if (marker2 < len2)
                {
                    ch2 = s2[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;
    }
}

here is a fast alphanumeric sort (can be used for other sorts with numerics too).

C# Alphanumeric Sorting http://www.dotnetperls.com/alphanumeric-sorting

var unordered = new[] { "100F", "50F", "SR100", "SR9" };
var ordered = unordered.OrderBy(s => s, new AlphanumComparatorFast());

and here is a nice article about the problem:

Sorting for Humans : Natural Sort Order http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html

Here is the AlphanumComparatorFast class in case the above link stops working The end of the page states "It can be used in any program with no restrictions" and the comment at the start of the code also indicates it is free for use:

// NOTE: This code is free to use in any program.
// ... It was developed by Dot Net Perls.

public class AlphanumComparatorFast : IComparer
{
    public int Compare(object x, object y)
    {
        string s1 = x as string;
        if (s1 == null)
        {
            return 0;
        }
        string s2 = y as string;
        if (s2 == null)
        {
            return 0;
        }

        int len1 = s1.Length;
        int len2 = s2.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = s1[marker1];
            char ch2 = s2[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 = s1[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

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

                if (marker2 < len2)
                {
                    ch2 = s2[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;
    }
}
七分※倦醒 2024-12-27 04:00:48

关于取自 http://www.dotnetperls.com/alphanumeric-sorting 的代码:解析当数字超出“int”范围时会抛出异常,这会导致我们的第三方网格工具出现异常“无法排序,因为 IComparer.Compare() 方法返回不一致的结果”。

我们更改了代码以使用decimal而不是int,并使用TryParse而不是Parse。

原始部分:

int thisNumericChunk = int.Parse(str1);
int thatNumericChunk = int.Parse(str2);
result = thisNumericChunk.CompareTo(thatNumericChunk);

我们的版本:

bool canParseStr1 = Decimal.TryParse(str1, out decimal thisNumericChunk);
bool canParseStr2 = Decimal.TryParse(str2, out decimal thatNumericChunk);
if (canParseStr1 && canParseStr2)
{
   result = thisNumericChunk.CompareTo(thatNumericChunk);
}
else
{
   // just return something, be deterministic
   result = str1.CompareTo(str2);
}

Regarding the code taken from http://www.dotnetperls.com/alphanumeric-sorting: Parse will throw an Exception when the number is out of the 'int' range, this lead to exception in our third party grid tool "Unable to sort because the IComparer.Compare() method returns inconsistent results."

We changed the code to use decimal instead of int, and TryParse instead of Parse.

Original part:

int thisNumericChunk = int.Parse(str1);
int thatNumericChunk = int.Parse(str2);
result = thisNumericChunk.CompareTo(thatNumericChunk);

Our version of it:

bool canParseStr1 = Decimal.TryParse(str1, out decimal thisNumericChunk);
bool canParseStr2 = Decimal.TryParse(str2, out decimal thatNumericChunk);
if (canParseStr1 && canParseStr2)
{
   result = thisNumericChunk.CompareTo(thatNumericChunk);
}
else
{
   // just return something, be deterministic
   result = str1.CompareTo(str2);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文