Сортировать IList‹T› на месте

Если у меня есть List<T>, я могу отсортировать его на месте, например,

myList.Sort((x,y) => x.MyComparisonMethod(y));

Если у меня есть IList<T>, я могу отсортировать его в новый список, используя

var sortedIList = unsortedIList.OrderBy(x => x.SortingValue);

Как я могу отсортировать IList<T> на месте?

Я использую С# .NET 4.5.1.


person tomsv    schedule 19.06.2015    source источник
comment
почему ты хочешь сделать это? В какой ситуации вы находитесь, которую unsortedIList = unsortedIList.OrderBy(x => x.SortingValue); не решит?   -  person David Arno    schedule 19.06.2015
comment
Я могу отсортировать его в новый список, используя нет, это не так, OrderBy не возвращает список, вам нужно вызвать ToList, чтобы создать новый список. Ваш вопрос, как использовать List.Sort с IList<T> вместо List<T>?   -  person Tim Schmelter    schedule 19.06.2015
comment
Вам нужно будет создать метод Sort и использовать его. Возьмем, к примеру, один из тех, что использует Mono.   -  person xanatos    schedule 19.06.2015


Ответы (3)


Напишите собственный метод расширения, используя заголовок ArrayList.Adapter в качестве IList<T> оболочки и вашей собственной CustomComparer, начиная с некоторого Сравнение делегат:

public static class IListExtensions
{
    public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
    {
        ArrayList.Adapter((IList)list).Sort(new CustomComparer<T>(comparison));
    }
}
person Francesco De Lisi    schedule 19.06.2015
comment
Почему -1? Какова цель -1 без объяснения причин? - person Francesco De Lisi; 19.06.2015
comment
Мне это действительно нравится, но я не смог найти CustomComparer в фреймворке. Вместо этого я использовал Comparer<T>.Create(comparison), который, кажется, делает то, что здесь задумано. - person dana; 19.08.2016

" Я могу отсортировать его в новый список, используя" нет, это не так, OrderBy не возвращает список, вам нужно вызвать ToList, чтобы создать новый список. Ваш вопрос, как использовать List.Sort с IList<T> вместо List<T>?

Вы можете написать метод расширения для IList<T>:

public static IList<T> Sort<T>(this IEnumerable<T> sequence, IComparer<T> comparer = null)
{
    var seqList = sequence as List<T>;
    if (seqList != null)
    {
        seqList.Sort((IComparer<T>)comparer);
        return seqList;
    }

    var seqArray = sequence as T[];
    if (seqArray != null)
    {
        Array.Sort(seqArray, (IComparer<T>)comparer);
        return seqArray;
    }

    return sequence.OrderBy(t => t, (IComparer<T>)comparer).ToList();
}

Теперь вы можете использовать Sort для списков, массивов или любой другой последовательности:

IList<string> strings = new[] { "B", "A", "C" };
strings.Sort();

Обновление: если вам нужно только одно для массивов или списков, вы можете использовать:

public static void Sort<T>(this IList<T> sequence, IComparer<T> comparer = null)
{
    var seqList = sequence as List<T>;
    if (seqList != null)
    {
        seqList.Sort((IComparer<T>)comparer);
        return;
    }

    var seqArray = sequence as T[];
    if (seqArray != null)
    {
        Array.Sort(seqArray, (IComparer<T>)comparer);
    }
}
person Tim Schmelter    schedule 19.06.2015
comment
Это, кажется, немного запутанное поведение. Он сортирует на месте List<T> и T[], но возвращает новый список для всего остального. - person Charles Mager; 19.06.2015
comment
@CharlesMager: вы можете сделать параметр IList<T> и удалить return sequence.OrderBy(t => t, (IComparer<T>)comparer).ToList(), если вы этого не хотите. Я просто хотел включить это, потому что OP упомянул об этом. Это комплексный подход. Тогда возвращаемое значение также является избыточным. - person Tim Schmelter; 19.06.2015
comment
Тогда у вас будет проблема «не все пути кода возвращают значение» как IList<T> != List<T> - что на самом деле является сутью вопроса. Как вы сортируете IList<T> на месте, если это может быть не List<T>? - person Charles Mager; 19.06.2015
comment
@CharlesMager: почему? Если вы хотите один только для IList<T>, вы можете сделать метод void. И списки, и массивы поддерживают метод void Sort. Отредактировал мой ответ, чтобы показать это. - person Tim Schmelter; 19.06.2015
comment
о да. Быть немного тупым... но дело в том, что если это не T[] или List<T>, он не будет выполнять никакой сортировки. Что, если я сдал Collection<T>, BindingList<T> и т. д.? - person Charles Mager; 19.06.2015
comment
@CharlesMager: сначала вы жаловались, что метод делает слишком много, а теперь делает слишком мало. OP, кажется, хочет только тот, который поддерживает IList<T> и сортирует на месте, поэтому без создания нового списка. - person Tim Schmelter; 19.06.2015
comment
В чем моя точка зрения - это не поддерживает IList<T>, оно поддерживает 2 его реализации. Я не пытаюсь намеренно спорить, я просто не думаю, что это отвечает на вопрос. - person Charles Mager; 19.06.2015
comment
@CharlesMager: извини, сегодня я плохо понимаю. Он принимает IList<T>, который мог бы f.e. быть List<string> или string[], и он сортирует их на месте. Что еще он может поддерживать, когда OP спрашивает, как я могу отсортировать IList‹T› на месте? Он не поддерживает IList, верно. Но этого не спрашивали. - person Tim Schmelter; 19.06.2015
comment
Но это также может быть Collection<T>, BindingList<T>, ObservableCollection<T>, любая другая из десятков реализаций IList<T> в BCL или пользовательская реализация. Они не будут сортироваться, но контракт подразумевает, что они будут. Извините, если я звучу аргументированно, поскольку у меня нет решения, кроме «самостоятельная сортировка». - person Charles Mager; 19.06.2015
comment
@CharlesMager: вы не можете поддерживать все, поскольку эти коллекции не поддерживают сортировку по умолчанию. Что вы можете сделать, так это бросить NotSupportedException во время выполнения, если тип не является списком или массивом. Но опять же, об этом не спрашивали. Если вам нужно его поддерживать, проще всего использовать LINQ. Например: new BindingList<T>(seqColl.OrderBy(x => x, comparer).ToList()) - person Tim Schmelter; 19.06.2015
comment
Я все еще пытаюсь понять, как вы утверждаете, что это не задано - вопрос буквально Как я могу отсортировать IList‹T› на месте? - нет упоминания, что он ограничен какими-либо конкретными реализациями. В дубликатах много общих решений. - person Charles Mager; 19.06.2015

Я подозреваю, что вы имеете в виду тот факт, что ваш OrderBy не будет компилироваться. Это потому, что он возвращает IOrderedEnumerable, который не является IList, вам нужно будет выполнить ToList() впоследствии, чтобы преобразовать его обратно в реализацию IList:

var sortedIList = unsortedIList.OrderBy(x => x.SortingValue).ToList();

И если вы хотите использовать свой собственный IComparer:

var sortedIList = unsortedIList.OrderBy(x => x.SortingValue, new MyComparer()).ToList();
person mattytommo    schedule 19.06.2015
comment
Это не отвечает на вопрос, так как не сортирует unsortedIList на месте - person David Arno; 19.06.2015