c#实现自然排序效果,按1,2,11而不是1,11,12,区分字母文字和数字

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#实现自然排序效果,按1,2,11而不是1,11,12,区分字母文字和数字相关的知识,希望对你有一定的参考价值。

排序有时候要考虑后缀。这样看起来比较自然。

参考了codeproject上一篇文章:http://www.codeproject.com/Articles/22978/Implementing-the-NET-IComparer-interface-to-get-a

然后自己写了个简单的,考虑到主要思想是上面那个文章上的,所以不做太多解释。代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StringOrder
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] array = new string[] { "序列11", "序列11s", "序列12", "序列1", "序列12s", "序列1s", "序列22s", "序列2", "序列3", "序列2w", "序列2q", "序列22r", "23r", "22r", "22", "2", "32", "42", "12", "1" };

            string[] array2 = array.OrderBy(a => a, new StringCompare1()).ToArray();
            Console.Read();
        }
    }
    public class StringCompare1 : IComparer<string>
    {
        public int Compare(string x, string y)
        {

            StringParser sx = new StringParser(x);
            StringParser sy = new StringParser(y);
            while (sx.TokenType != StringParser.ETokenType.Nothing || sy.TokenType != StringParser.ETokenType.Nothing)
            {
                if (sx.TokenType == StringParser.ETokenType.Numberic && sy.TokenType == StringParser.ETokenType.Numberic)
                {
                    return (int)(sx.DoubleValue - sy.DoubleValue);
                } 
                if (string.Compare(sx.StringValue, sy.StringValue) != 0)
                {
                    return string.Compare(sx.StringValue, sy.StringValue);
                }
                else
                {
                    sx.NextToken();
                    sy.NextToken();
                }
            }
            return 0;
        }
    }

    public class StringParser
    {
        private string _value;
        private char _curChar;
        private int _curIndex = 0;
        private int _length;
        private ETokenType _tokenType = ETokenType.Character;
        public ETokenType TokenType { get { return _tokenType; } }

        private string _stringValue;
        public string StringValue { get { return _stringValue; } }

        private double _doubleValue;
        public double DoubleValue { get { return _doubleValue; } }


        public StringParser(string val)
        {
            _value = val;
            _length = val.Length;
            NextChar();
            NextToken();
        }

        public void NextToken()
        {
            if (_curChar == ‘\0‘)
            {
                _tokenType = ETokenType.Nothing;
                _stringValue = null;
            }
            else if (char.IsDigit(_curChar))
            {
                int startIndex = _curIndex;
                while (char.IsDigit(_curChar) || _curChar == ‘.‘)
                {
                    NextChar();
                }
                string temp = _value.Substring(startIndex-1, _length - startIndex+1);
                if (double.TryParse(temp, out _doubleValue))
                {
                    _tokenType = ETokenType.Numberic;
                }
                else
                {
                    _tokenType = ETokenType.Character; 
                } 
                _stringValue = temp;
            }
            else if (char.IsLetter(_curChar))
            {
                _tokenType = ETokenType.Character;
                int startIndex = _curIndex;
                while (char.IsLetter(_curChar))
                {
                    NextChar();
                }
                _stringValue = _value.Substring(startIndex-1,_curIndex-startIndex);
            }
            else
            {
                NextChar();
            }
        }

        private void NextChar()
        {
            if (_curIndex >= _length)
            {
                _curChar = ‘\0‘;
                return;
            }
            else
            {
                _curChar = _value[_curIndex];
                _curIndex += 1;
            }
           
        }
        public enum ETokenType
        {
            Nothing,
            Character,
            Numberic,
        }
    }
}

 

以上是关于c#实现自然排序效果,按1,2,11而不是1,11,12,区分字母文字和数字的主要内容,如果未能解决你的问题,请参考以下文章

C#自动更新Excel报表而不改变原有样式(2021.8.11)

Python字典如何按键(1,2,3,4…)输出,而不是(1,10,11…)?

sql 按指定规则排序,例如 按 1,3,2排序 而不是1,2,3

ID 按字母顺序而不是数字顺序

按拆分列内容排序

如何让 jQuery 效果按顺序运行,而不是同时运行?