Как отсортировать коллекцию <T>на месте? - PullRequest
14 голосов
/ 17 февраля 2012

У меня есть общая коллекция:

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>?

Ответы [ 6 ]

12 голосов
/ 17 февраля 2012

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

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(); }
}
1 голос
/ 17 февраля 2012

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

0 голосов
/ 30 сентября 2016

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

0 голосов
/ 17 ноября 2014

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

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;
}
0 голосов
/ 17 февраля 2012

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).

0 голосов
/ 17 февраля 2012

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

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