Как отсортированные наборы для С# работают с пользовательскими объектами?

Я пытаюсь поиграть с отсортированными наборами в С# для пользовательских объектов, и по какой-то причине кажется, что отсортированные наборы могут не использовать ссылки на объекты для хранения данных.

В следующем фрагменте кода я использую пользовательский IComparer, чтобы полагаться на свойство Counts пользовательского класса. Но по какой-то причине это, похоже, влияет на функциональность добавления. и строка counter.Add(two) не вносит никаких дополнений в набор, даже если это другая ссылка и имеет разные значения для двух свойств.

Я что-то пропустил? У меня что-то не так в том, как SortedSets должны работать в С#?

Фрагмент кода

    public class SortedStructureTesting
    {
        public void TestingSortedSets()
        {
            SortedSet<CounterSetup> counter = new SortedSet<CounterSetup>(new CompareCounts());

            CounterSetup one = new CounterSetup(1);
            CounterSetup two = new CounterSetup(2);
            CounterSetup three = new CounterSetup(3, 2);

            counter.Add(one);
            counter.Add(two); // Does not work. This value does not get added to the set.
            counter.Add(three);

            var max = counter.Max;
            counter.Remove(max);
            var sec = counter.Max;
            counter.Remove(sec);
        }

        public class CounterSetup
        {
            public static Random random = new Random();
            public CounterSetup(int no, int cnt = 1)
            {
                Number = no;
                Count = cnt;
                Blah = new string(Guid.NewGuid().ToString());
            }

            public int Number { get; private set; }

            public int Count { get; set; }

            public string Blah { get; private set; }
        }

        public class CompareCounts : IComparer<CounterSetup>
        {
            public int Compare(CounterSetup one, CounterSetup two)
            {
                return one.Count.CompareTo(two.Count);
            }
        }
    }

Спасибо, что заглянули и помогли!

[Sorted]Set не может быть двух или более одинаковых предметов. Вы сравниваете items с Count; поэтому Count должен быть различен. Обратите внимание, что экземпляры one и two имеют одинаковые Count == 1, поэтому two проигнорировано (не добавлено)
Dmitry Bychenko 14.12.2020 07:09

Похоже, SortedSet принимает только уникальные значения для Sort-Property.

Nikolaus 14.12.2020 07:10

Привет, @DmitryBychenko, спасибо, что так быстро ответили мне! Я думал, что отсортированный набор будет обрабатывать уникальность на основе пользовательской ссылки на объект, используя свойство сортировки для сохранения сортировки объектов. Разве это невозможно?

rmehta 14.12.2020 07:16

@Nikolaus, да .. по какой-то причине определенно кажется, что ссылка не используется для уникальности .. Не знаете ли вы, есть ли какая-нибудь структура, которую я мог бы использовать для поддержания уникальности на основе одного свойства и сортировки с использованием другого ? без, понимаете, создания собственной структуры данных?

rmehta 14.12.2020 07:20

@devNull ДА! Спасибо!

rmehta 14.12.2020 07:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
795
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну [Sorted]Set может содержать только отдельные элементы; то есть Set не может иметь еще два одинаковых элемента. Вы сравниваете предмет (рассматриваете их как равные) в отношении Count: если два предмета имеют одинаковые Count, они считаются равными. В вашем коде

  CounterSetup one = new CounterSetup(1);         // one.Count == 1
  CounterSetup two = new CounterSetup(2);         // two.Count == 1
  CounterSetup three = new CounterSetup(3, 2);    // three.Count == 2

у вас есть one.Count == two.Count == 1, поэтому one и two равны для отсортированного набора counter. Когда вы добавляете элементы, второй (то есть two) игнорируется:

  counter.Add(one);
  counter.Add(two); // Ignored: there's already an item (one) with the same Count
  counter.Add(three);

Если вам нужны отдельные критерии (один для Equals, а другой для порядка), вы можете попробовать старый добрый HashSet, который вы можете представить как заказанный с помощью Linq:

  using System.Linq;

  ...

  // Items in counter are unique (based on MyEqualityComparer)
  HashSet<CounterSetup> counter = new HashSet<CounterSetup>(
    new MyEqualityComparer()
  );

  // Now we order counter items by different criterium (here we sort by `Count`)
  var ordered = counter
    .OrderBy(item => item.Count);

Привет, @Dmitry, я понимаю, что ты имеешь в виду.. Но это выглядит очень странно.. В конце концов, если мы используем HashSet<CounterSetup> counter = new HashSet<CounterSetup>(); у нас есть все эти 3 объекта там. Есть ли способ получить все 3 объекта в отсортированном наборе (или какой-либо другой отсортированной коллекции) и при этом отсортировать их по другому свойству?

rmehta 14.12.2020 07:23

Привет, Дмитрий, последнее редактирование твоего поста определенно помогает мне решить мои проблемы! Спасибо!!

rmehta 14.12.2020 07:26

@rmehta: увы, SortedSet<T> это RB-Tree (Red Black Tree) и он должен работать с одним критерием.

Dmitry Bychenko 14.12.2020 07:27

Ах! Понятно... красно-черное дерево с 1 критерием действительно многое объясняет... спасибо, что выручили меня в этот странный час!

rmehta 14.12.2020 07:30

Другие вопросы по теме