Nano Hash - криптовалюты, майнинг, программирование

Где моя реализация IComparable работает неправильно?

namespace SortableLists
{
    using System;
    using System.Collections.Generic;

    public class Program
    {
        private static void Main() {
            var list = new List<ListItem>
                           {
                               new ListItem {AdmissionCode = "801r", Name = "Rajesh Koothrappali", RollNumber = 54},
                               new ListItem {AdmissionCode = "892k", Name = "Leonard Leakey Hofstadter", RollNumber = 34},
                               new ListItem {AdmissionCode = "1203a", Name = "Sheldon Lee Cooper", RollNumber = 46},
                               new ListItem {AdmissionCode = "802x", Name = "Howard Wolowitz", RollNumber = 98}
                           };
            list.ForEach(x => Console.WriteLine(x.RollNumber + ","+x.Name + "," + x.AdmissionCode));

            Console.Write("\n");
            list.Sort();
            list.ForEach(x => Console.WriteLine(x.RollNumber + "," + x.Name + "," + x.AdmissionCode));

            Console.ReadKey();
        }
    }

    public class ListItem : IComparable<ListItem>
    {
        public int RollNumber { get; set; }
        public string Name { get; set; }
        public string AdmissionCode { get; set; }

        #region Implementation of IComparable<in ListItem>

        public int CompareTo(ListItem other) {
            return AdmissionCode.CompareTo(other.AdmissionCode);
        }

        #endregion
    }
}

Я не знаю, что это за сортировка, когда код допуска 1203 доктора Шелдона появляется вверху списка после сортировки??? я ожидал 801 802 803 и 1203... кто-нибудь может объяснить?

11.01.2011

Ответы:


1

Числа, которые вы сравниваете, рассматриваются не как числа, а как строки! А со строками буква «1» стоит перед «8», поэтому большее число появляется первым, потому что при обработке в виде текста порядок другой.

Я рекомендую вам преобразовать это поле в int, если вы хотите рассматривать его как единое целое.

Изменить: для вашего отредактированного вопроса (поле теперь также содержит буквы) вам нужно будет написать пользовательскую логику сравнения, чтобы сравнивать их в нужном вам порядке.

Например, я предполагаю, что вы хотите, чтобы логика была такой:

  1. Разделить код на цифры и буквы.
  2. Сравнивать только числа (как int).
  3. Если числовые части одинаковы для обоих значений, сравните остальные как строку.

Реализуйте эту логику (или любую другую логику, которую вы действительно хотите) в своем методе CompareTo, и вы получите желаемый порядок.

Код для такой логики может быть таким:

public class ListItem : IComparable<ListItem>
{
    public int RollNumber { get; set; }
    public string Name { get; set; }
    public string AdmissionCode { get; set; }

    private static readonly char[] Numbers = new[]
    {
        '0',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9'
    };

    #region Implementation of IComparable<in ListItem>
    public int CompareTo(ListItem other)
    {
        // Assumes AdmissionCode is in ####ABC format,
        // with at least one number and any amount of letters.
        string myNumberPart, myRemainingPart;
        string otherNumberPart, otherRemainingPart;

        SplitAdmissionCode(AdmissionCode, out myNumberPart, out myRemainingPart);
        SplitAdmissionCode(other.AdmissionCode, out otherNumberPart, out otherRemainingPart);

        int myNumber = int.Parse(myNumberPart);
        int otherNumber = int.Parse(otherNumberPart);

        int result = myNumber.CompareTo(otherNumber);

        // Numbers are different.
        if (result != 0)
            return result;

        // Numbers are same. Use text compare for the remaining part.
        return myRemainingPart.CompareTo(otherRemainingPart);
    }

    private void SplitAdmissionCode(string code, out string numbersPart, out string remainingPart)
    {
        int lastNumberIndex = code.LastIndexOfAny(Numbers);

        numbersPart = code.Substring(0, lastNumberIndex + 1);

        if (lastNumberIndex == code.Length - 1)
            remainingPart = "";
        else
            remainingPart = code.Substring(lastNumberIndex + 1);
    }
    #endregion
}
11.01.2011

2

Вы сортируете строки, а не числа. Строка CompareTo не учитывает длину.

EDIT (для вашего отредактированного вопроса): при сортировке строк, начинающихся с чисел, сортировка метода CompareTo вряд ли даст ожидаемые результаты, поскольку все, что он делает, это алфавитный порядок.

11.01.2011

3

Строка "1203" меньше "801". Вы можете попытаться преобразовать строки в числа перед сравнением (если они по существу представляют числовые значения)

11.01.2011

4

Это ожидаемая функциональность, как уже отмечали другие.
Если вы хотите такой порядок, как 801r, 802x, 892k, 1203a, сделайте это

public class ListItem : IComparable<ListItem>
{
    public int RollNumber { get; set; }
    public string Name { get; set; }
    public string AdmissionCode { get; set; }

    public int CompareTo(ListItem other) {
        return ExtractNumbers(this.AdmissionCode).CompareTo(ExtractNumbers(other.AdmissionCode));
    }
    private int ExtractNumbers(string expr) {
        return Convert.ToInt32(String.Join(null,System.Text.RegularExpressions.Regex.Split(expr, "[^\\d]")));
    }
}
11.01.2011

5

Если вы хотите, чтобы это было просто:

public class ListItem : IComparable<ListItem>
{
    public int RollNumber { get; set; }
    public string Name { get; set; }
    public string AdmissionCode { get; set; }

    #region Implementation of IComparable<in ListItem>

    public int CompareTo(ListItem other)
    {
        return this.AdmissionCode.Length != other.AdmissionCode.Length
            ? this.AdmissionCode.Length.CompareTo(other.AdmissionCode.Length)
            : this.AdmissionCode.CompareTo(other.AdmissionCode);
    }

    #endregion
}
11.01.2011
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..