Как отсортировать коллекцию <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>
?
Ответы
Ответ 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)
и отсортируйте его как массив.