Пользовательский общий компаратор чисел и текста в С# для сортировки числового/строкового списка?

Я хочу создать аналогичный компаратор числа и текста, описанный в Как создать собственный общий компаратор числа и текста в 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. N/A, --, -888, -0.98, 0.00, 100
  2. Джим, Кен, Н.А., Питер, Смит, --

Но я хочу в сортировке строк: "" или -- должны стоять первыми, а не последними в порядке возрастания. Числовая сортировка исключена.

Таким образом, ожидаемый результат будет следующим:

  1. Числовая сортировка по возрастанию -> N/A, --,-888, -0.98, 0.00, 100
  2. Сортировка строк по возрастанию -> , --, Jim, Ken, NA, Peter, Smith

Можно ли этого добиться?


person Sanvi Deshpande    schedule 13.01.2016    source источник
comment
Что вы пробовали? Предоставьте хороший минимальный воспроизводимый пример с точным объяснением того, что делает этот код и чем он отличается от того, что вы хотите. .   -  person Peter Duniho    schedule 14.01.2016
comment
Обновлен фрагмент кода. Спасибо!   -  person Sanvi Deshpande    schedule 14.01.2016
comment
Спасибо за код. К сожалению, я до сих пор не очень понимаю вопрос. Две проблемы: 1) примеры ожидаемых результатов не согласуются друг с другом. В первом строка "--" идет после "N/A", а во втором перед "NA" (и всеми остальными нечисловыми). Судя по твоему описанию, я думаю, ты захочешь его и до "N/A". Почему бы и нет?   -  person Peter Duniho    schedule 14.01.2016
comment
2) Я не вижу в вашем примере кода ничего, что пыталось бы отсортировать "--" и "" перед другими строками; т. е. я не вижу что вы пробовали. Я ожидаю, что вы можете использовать ту же технику, которую вы сейчас используете для числовых значений, т. е. проверять ввод для конкретного шаблона, который вы хотите обрабатывать исключительно, а затем обрабатывать их соответствующим образом; с чем конкретно у вас проблемы?   -  person Peter Duniho    schedule 14.01.2016


Ответы (1)


Насколько я понимаю, вам требуется 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));
person Sumit Deshpande    schedule 23.01.2016