Как создать собственный общий числовой текстовый компаратор в C# для сортировки числового / строкового списка?
У меня есть числовой текстовый список, и я хочу создать общую пользовательскую логику сравнения, чтобы отсортировать этот список (ы) с помощью C#. Например
var numericList = new List<string>{"100", "--", "-0.98", "N/A", "0.00", "-888"};
var stringList = new List<string> {"Smith", "--", "Peter", "", "Jim", "Ken", "NA"};
который содержит некоторые специальные символы, такие как -, N/A, пробел и т. д. И ожидаемый результат после сортировки будет - Для NemericList Ascending -> N / A, -, -888, -0,98, 0,00, 100Для StringList Ascending -> Джим, Кен, N / A, Питер, Смит, Пусто, -
Я создал следующую пользовательскую логику сравнения, которая выполняет некоторый уровень сортировки, но не соответствует ожидаемому результату. Пожалуйста, предложите мне способ достичь этого.
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; } return isS1Numeric ? 1 : (isS2Numeric ? -1 : String.Compare(s1, s2, StringComparison.OrdinalIgnoreCase)); } }
var comparer = new NumberTextComparer();
var numericSortedListASC = numericList.OrderBy(str => str, comparer);
var stringSortedListASC = stringList.OrderBy(str => str, comparer);
1 ответ
Ваш код работает правильно. Смотри сюда. Результаты:
--, N/A, -888, -0.98, 0.00, 100
, --, Jim, Ken, NA, Peter, Smith
Проблема в том, что вы предполагаете, что "" и "-" идут после букв. Так как они имеют более низкую позицию в таблице ascii, они идут первыми.
Это было бы просто исправить. Попробуй здесь
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);
return s1StartsWithLetter ? -1 : 1;
}