Natural Sort Order in C#

后端 未结 17 2540
野性不改
野性不改 2020-11-21 04:54

Anyone have a good resource or provide a sample of a natural order sort in C# for an FileInfo array? I am implementing the IComparer interface in

17条回答
  •  萌比男神i
    2020-11-21 05:47

    A version that's easier to read/maintain.

    public class NaturalStringComparer : IComparer
    {
        public static NaturalStringComparer Instance { get; } = new NaturalStringComparer();
    
        public int Compare(string x, string y) {
            const int LeftIsSmaller = -1;
            const int RightIsSmaller = 1;
            const int Equal = 0;
    
            var leftString = x;
            var rightString = y;
    
            var stringComparer = CultureInfo.CurrentCulture.CompareInfo;
    
            int rightIndex;
            int leftIndex;
    
            for (leftIndex = 0, rightIndex = 0;
                 leftIndex < leftString.Length && rightIndex < rightString.Length;
                 leftIndex++, rightIndex++) {
                var leftChar = leftString[leftIndex];
                var rightChar = rightString[leftIndex];
    
                var leftIsNumber = char.IsNumber(leftChar);
                var rightIsNumber = char.IsNumber(rightChar);
    
                if (!leftIsNumber && !rightIsNumber) {
                    var result = stringComparer.Compare(leftString, leftIndex, 1, rightString, leftIndex, 1);
                    if (result != 0) return result;
                } else if (leftIsNumber && !rightIsNumber) {
                    return LeftIsSmaller;
                } else if (!leftIsNumber && rightIsNumber) {
                    return RightIsSmaller;
                } else {
                    var leftNumberLength = NumberLength(leftString, leftIndex, out var leftNumber);
                    var rightNumberLength = NumberLength(rightString, rightIndex, out var rightNumber);
    
                    if (leftNumberLength < rightNumberLength) {
                        return LeftIsSmaller;
                    } else if (leftNumberLength > rightNumberLength) {
                        return RightIsSmaller;
                    } else {
                        if(leftNumber < rightNumber) {
                            return LeftIsSmaller;
                        } else if(leftNumber > rightNumber) {
                            return RightIsSmaller;
                        }
                    }
                }
            }
    
            if (leftString.Length < rightString.Length) {
                return LeftIsSmaller;
            } else if(leftString.Length > rightString.Length) {
                return RightIsSmaller;
            }
    
            return Equal;
        }
    
        public int NumberLength(string str, int offset, out int number) {
            if (string.IsNullOrWhiteSpace(str)) throw new ArgumentNullException(nameof(str));
            if (offset >= str.Length) throw new ArgumentOutOfRangeException(nameof(offset), offset, "Offset must be less than the length of the string.");
    
            var currentOffset = offset;
    
            var curChar = str[currentOffset];
    
            if (!char.IsNumber(curChar))
                throw new ArgumentException($"'{curChar}' is not a number.", nameof(offset));
    
            int length = 1;
    
            var numberString = string.Empty;
    
            for (currentOffset = offset + 1;
                currentOffset < str.Length;
                currentOffset++, length++) {
    
                curChar = str[currentOffset];
                numberString += curChar;
    
                if (!char.IsNumber(curChar)) {
                    number = int.Parse(numberString);
    
                    return length;
                }
            }
    
            number = int.Parse(numberString);
    
            return length;
        }
    }
    

提交回复
热议问题