C# 中的自定义通用数字文本比较器,用于对数字/字符串列表进行排序

本文关键字:数字 用于 字符串 列表 排序 比较器 自定义 文本比较 文本 | 更新日期: 2023-09-27 18:30:14

我想创建一个类似于如何在 C# 中创建自定义通用数字文本比较器以对数字/字符串列表进行排序?中所述的数字文本比较器。

public class NumberTextComparer : IComparer<string>
    {
        public int Compare(string s1, string s2)
        {
            double number1, number2;
            var isS1Numeric = double.TryParse(s1, out number1);
            var isS2Numeric = double.TryParse(s2, out number2);
            if (isS1Numeric && isS2Numeric)
            {
                if (number1 > number2) return 1;
                if (number1 < number2) return -1;
                return 0;
            }
            if (isS1Numeric)
                return 1;
            if (isS2Numeric)
                return -1;
            bool s1StartsWithLetter = char.IsLetter(s1.FirstOrDefault());
            bool s2StartsWithLetter = char.IsLetter(s2.FirstOrDefault());
            if (s1StartsWithLetter == s2StartsWithLetter)
                return String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
            if (s1StartsWithLetter)
                return -1;
            return 1;
        }
    }
var numericList = new List<string>{"100", "--", "-0.98", "N/A", "0.00", "-888"};
var stringList = new List<string> {"Smith", "--", "Peter", "", "Jim", "Ken", "NA"};
Console.WriteLine(String.Join(", ", numericList.OrderBy(v => v, new NumberTextComparer())));
Console.WriteLine(String.Join(", ", stringList.OrderBy(v => v, new NumberTextComparer())));

这给出了以下输出:

  1. 不适用, --, -888, -0.98, 0.00, 100
  2. 吉姆,肯,NA,彼得,史密斯,,--

但是我想在字符串排序中:""--应该排在第一位,而不是按升序排在最后。数字排序除外。

因此,预期结果将是:

  1. 数字排序 asc -> N/A, --,-888, -0.98, 0.00, 100
  2. 字符串排序 asc -> , --, Jim, Ken, NA, Peter, Smith

有可能做到这一点吗?

C# 中的自定义通用数字文本比较器,用于对数字/字符串列表进行排序

根据我的理解,在数字和字符串数据的情况下,您需要 2 种不同的排序行为。因此,您可以通过传递所需的类型来实现这一点,如下所示-

 public enum SortColumnType
 {
        Numeric=1,
        String=2
 }
public class NumberTextComparer : IComparer<string>
    {
        public SortColumnType ColumnType { get; set; }
        public NumberTextComparer(SortColumnType columnType)
        {
            ColumnType = columnType;
        }
        private int CustomNumberSort(string s1, string s2)
        {
            double number1, number2;
            var isS1Numeric = double.TryParse(s1, out number1);
            var isS2Numeric = double.TryParse(s2, out number2);
            if (isS1Numeric && isS2Numeric)
            {
                if (number1 > number2) return 1;
                if (number1 < number2) return -1;
                return 0;
            }
            if (isS1Numeric)
                return 1;
            if (isS2Numeric)
                return -1;
            var s1StartsWithLetter = !string.IsNullOrEmpty(s1) && char.IsLetterOrDigit(s1[0]);
            var s2StartsWithLetter = !string.IsNullOrEmpty(s2) && char.IsLetterOrDigit(s2[0]);
            if (s1StartsWithLetter == s2StartsWithLetter)
                return String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
            if (s1StartsWithLetter)
                return -1;
            return 1;
        }
        public int Compare(string s1, string s2)
        {
            return ColumnType.Equals(SortColumnType.Numeric)
                ? CustomNumberSort(s1, s2)
                : String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
        }
    }
stringList.OrderBy(str => str, new NumberTextComparer(SortColumnType.String));
numericList.OrderBy(str => str, new NumberTextComparer(SortColumnType.Numeric));