Есть ли отсортированный тип коллекции в .NET? - PullRequest
25 голосов
/ 13 октября 2008

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

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

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

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

Ответы [ 7 ]

20 голосов
/ 13 октября 2008

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

12 голосов
/ 07 февраля 2014

Просто чтобы сделать комментарий EBarr в качестве ответа, существует. Конечно, это набор, что означает, что вы не можете иметь дубликаты.

3 голосов
/ 24 сентября 2009

Если вы просто хотите придерживаться стандартных коллекций, то функция 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()) всякий раз, когда вы хотите отсортировать список, прежде чем получить к нему доступ. Я понимаю, что это может быть не так просто, как контейнер, который автоматически сортируется каждый раз, когда вы добавляете новый объект, но для многих (как я!) Этого может быть достаточно для успешного выполнения работы без дополнительных библиотек.

3 голосов
/ 13 октября 2008

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

2 голосов
/ 13 октября 2008

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

0 голосов
/ 13 октября 2008

Вот старая уловка, которую я использовал в 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
Правда

0 голосов
/ 13 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...