Подтвердить что ты не робот

Как отсортировать коллекцию <T> на месте?

У меня есть общий набор:

public Items : Collection<Object>
{
   protected override void InsertItem(int index, Object item)
   {
      base.InsertItem(index, item);
      ...
   }

   protected override void RemoveItem(int index)
   {
      base.RemoveItem(index);
      ...
   }

   protected override void SetItem(int index, Object item)
   {
      base.SetItem(index, item);
      ...
   }

   protected override void ClearItems()
   {
      base.ClearItems();
      ...
   }

Теперь мне нужен способ сортировки этой коллекции на месте.

Бонус-чат

Я попытался преобразовать свой класс в использование List<T>, а не Collection<T> (так как Collection<T> не поддерживает концепцию заказа). Тогда это позволило вызвать метод Sort:

this.Items.Sort(SortCompareCallback);

protected virtual int SortCompareCallback(Object x, Object y)
{
   return OnCompareItems(new SortCompareEventArgs(x, y, this.sortColumnIndex, direction));
}

Но тогда я теряю виртуальные методы при изменении списка.

Я думал об использовании Linq, но проблема с этим:

  • Я не знаю, как вызвать обратный вызов из выражения Linq
  • Linq не сортирует коллекцию, он может только возвращать новый

Как я могу сортировать общий Collection<T>?

4b9b3361

Ответ 1

Если вам не нужно иметь виртуальные переопределения, вызываемые во время сортировки, вы должны сделать что-то вроде этого:

class SortableCollection<T> : Collection<T>
{
    private readonly List<T> _list;

    public SortableCollection() : this(new List<T>()) {}
    public SortableCollection(List<T> list) : base(list)
    {
        _list = list;
    }
    public void Sort() { _list.Sort(); }
}

Или это:

class SortableCollection<T> : Collection<T>
{
    public SortableCollection() : this(new List<T>()) {}
    public SortableCollection(List<T> list) : base(list) {}
    public void Sort() { ((List<T>)Items).Sort(); }
}

Ответ 2

Вы можете использовать SortedList<T> (который также реализует ICollection<T>, поэтому вы можете рассматривать его как коллекцию, если хотите).

Ответ 3

Если вам нужен отсортированный список с уведомлением об изменении контента, вы должны посмотреть BindingList

Ответ 4

Collection<T> имеет индекс. Если вы действительно хотите сортировать элементы на своем месте, вы можете реализовать любой алгоритм сортировки, который вы предпочитаете с помощью индексатора. Вот пример, который с помощью соответствующей коллекции может принимать O (N ^ 3)...

void SortInPlace(Collection<T> col)
{
    for(int i=0; i<col.Count - 1; i++)
        for(int j=i+1; j<col.Count; j++)
            if(col[i] < col[j]) // This won't compile, but you get the jist
                Swap col[i] and col[j]
}

Вы можете реализовать один из алгоритмов O (NlogN), чтобы получить производительность сортировки O (N ^ 2logN), если ваша коллекция предлагает только доступ к элементу O (N).

Ответ 5

Да, вы можете сортировать коллекцию, попробуйте это:

public ICollection<T> getSortedData(ICollection<T> collection, string property, string direction)
{
    switch (direction.Trim())
    {
        case "asc":
            collection = ((from n in collection
                           orderby
                           n.GetType().GetProperty(property).GetValue(n, null)
                           select n).ToList<T>()) as ICollection<T>;
        break;
        case "desc":
            collection = ((from n in collection
                           orderby
                           n.GetType().GetProperty(property).GetValue(n, null)
                           descending
                           select n).ToList<T>()) as ICollection<T>;
        break;
    }
    return collection;
}

Ответ 6

Используйте ArrayList.Adapter(yourCollection) и отсортируйте его как массив.