在 C# 中自定义通用数字文本比较器来排序 numeric/string 列表?
Custom common number-text comparer in C# to sort numeric/string list?
我想创建一个与 中描述的类似的数字文本比较器。
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())));
给出以下输出:
- N/A, --, -888, -0.98, 0.00, 100
- 吉姆、肯、NA、彼得、史密斯、--
但我希望在字符串排序中:""
或 --
应该按升序排在第一位而不是最后一位。数字排序除外。
因此预期结果将是:
- 数字升序排序 ->
N/A, --,-888, -0.98, 0.00, 100
- 字符串升序排序 ->
, --, Jim, Ken, NA, Peter, Smith
有可能实现吗?
据我了解,对于数字和字符串数据,您需要 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));
我想创建一个与
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())));
给出以下输出:
- N/A, --, -888, -0.98, 0.00, 100
- 吉姆、肯、NA、彼得、史密斯、--
但我希望在字符串排序中:""
或 --
应该按升序排在第一位而不是最后一位。数字排序除外。
因此预期结果将是:
- 数字升序排序 ->
N/A, --,-888, -0.98, 0.00, 100
- 字符串升序排序 ->
, --, Jim, Ken, NA, Peter, Smith
有可能实现吗?
据我了解,对于数字和字符串数据,您需要 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));