Есть ли отсортированный тип коллекции в.NET?

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

Использование:

  • Случайная вставка
  • Частое прохождение в порядке
  • В идеале не работать с ключами отдельно от реального объекта, используя функцию сравнения для сортировки.
  • Стабильная сортировка для эквивалентных объектов желательна, но не обязательна.
  • Произвольный доступ не требуется.

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

7 ответов

Решение

Возможно, вы захотите взглянуть на Коллекции Энергии Wintellect. Он доступен на CodePlex и содержит довольно много полезных коллекций. Коллекция OrderedBag в проекте - это именно то, что вы ищете. Он по существу использует красно-черное дерево, чтобы обеспечить довольно эффективную сортировку.

Чтобы сделать комментарий EBarr в качестве ответа, есть SortedSet<T> начиная с.NET 4.0. Конечно, это набор, что означает, что вы не можете иметь дубликаты.

Если вы просто хотите придерживаться стандартных коллекций, то Sort(IComparer<>) функция List<> класс часто игнорируется. Все, что вам нужно сделать, это создать подходящий Comparer<> для ваших объектов. Например:

public class PositionDateComparer : IComparer<VehiclePosition>
{
    public int Compare(VehiclePosition x, VehiclePosition y)
    {
        if (x.DateTime == DateTime.MinValue)
        {
            if (y.DateTime == DateTime.MinValue)
            {
                // If x is null and y is null, they're
                // equal. 
                return 0;
            }

            // If x is null and y is not null, y
            // is greater. 
            return -1;
        }

        // If x is not null...
        //
        if (y.DateTime == DateTime.MinValue)
        // ...and y is null, x is greater.
        {
            return 1;
        }

        // ...and y is not null, compare the dates
        //
        if (x.DateTime == y.DateTime)
        {
            // x and y are equal
            return 0;
        }

        if (x.DateTime > y.DateTime)
        {
            // x is greater
            return 1;
        }

        // y is greater
        return -1;
    }
}

Затем просто выполните vehiclePositionsList.Sort(new PositionDateComparer()) всякий раз, когда вы хотите отсортировать список, прежде чем получить к нему доступ. Я понимаю, что это может быть не так просто, как контейнер, который автоматически сортируется каждый раз, когда вы добавляете новый объект, но для многих (таких как я!) Этого может быть достаточно для успешного выполнения работы без дополнительных библиотек.

Я бы расширил ваш собственный класс списка, который, как вы упомянули, просто сортирует после каждой вставки. Поскольку ваши вставки встречаются нечасто, снижение производительности будет минимальным, и сортировка почти отсортированного списка будет быстрой в любом случае. Расширьте общий список и переопределите метод Add для немедленной сортировки. Если производительность становится проблемой, вы можете вставить ее, чтобы сэкономить время. Кроме того, вы можете поставить в очередь свои вставки, чтобы выполнить одну вставку обхода для всех значений, которые вы хотите вставить.

Как я уже упоминал ранее здесь, у библиотеки C5 Generic Collection есть подходящий контейнер для вас.

Если ключ также является атрибутом объекта, вы можете попробовать System.Collections.ObjectModel.KeyedCollection<TKey, TItem>, Это абстрактный класс, но если ваш ключ является просто свойством элемента, его очень просто извлечь.

Вот старый трюк, который я использовал в VB6 для сортировки по алфавиту: используйте объект System.Windows.Forms ListBox и установите для его свойства "Sorted" значение true. В C# вы можете вставить любой объект в список, и он отсортирует объект в алфавитном порядке по значению ToString():

для модуля класса:


использование System.Windows.Forms;

    static void Main(string[] args)
    {
        ListBox sortedList = new ListBox();
        sortedList.Sorted = true;

        sortedList.Items.Add("foo");
        sortedList.Items.Add("bar");
        sortedList.Items.Add(true);
        sortedList.Items.Add(432); 

        foreach (object o in sortedList.Items)
        {
            Console.WriteLine(o);
        }

        Console.ReadKey();
    }

Это будет отображать:

432
бар
Foo
Правда

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