在适当的位置排序IList <t>?</t>

时间:2013-10-03 19:04:33

标签: .net

.NET是否为IList提供了就地排序功能?我需要对集​​合本身进行排序,而不是创建新的集合。

编辑:我需要进行排序的原因是为了避免重新绘制UI,除非实际发生了某些变化。如果只有一个项目不合适,我不想创建一百个新的自定义控件。

编辑:同样,这是关于就地排序的问题,而不仅仅是排序。

4 个答案:

答案 0 :(得分:3)

就地Quicksort / InsertionSort / ShellSort实施情况如何:

public static class InPlaceQuickSort {
    private static void Swap<T>(IList<T> set, int left, int right) {
        T temp = set[left];
        set[left] = set[right];
        set[right] = temp;
    }

    private static Int32 Partition<T>(IList<T> set, int lBound, int rBound)
        where T : IComparable<T> {
        T pivot = set[rBound];
        int left = lBound - 1;
        int right = rBound;

        while (true) {

            while (set[++left].CompareTo(pivot) < 0) ;
            while (set[--right].CompareTo(pivot) > 0) if (left == right) break;

            if (left >= right) break;
            Swap(set, left, right);
        }

        Swap(set, left, rBound);
        return left;
    }

    private static IList<T> QuickSort<T>(IList<T> set, int lBound, int rBound)
        where T : IComparable<T> {
        if (lBound >= rBound) return set;

        Int32 pivot = Partition(set, lBound, rBound);
        QuickSort(set, lBound, pivot - 1);
        QuickSort(set, pivot + 1, rBound);

        return set;
    }

    public static IList<T> InsertionSort<T>(this IList<T> set)
        where T : IComparable<T> {
        for (Int32 index = 1; index < set.Count; index++) {
            for (Int32 insertion = index; insertion > 0 && set[insertion - 1].CompareTo(set[insertion]) > 0; insertion--) {
                Swap(set, insertion - 1, insertion);
            }
        }

        return set;
    }

    public static IList<T> ShellSort<T>(this IList<T> set)
        where T : IComparable<T> {
        Int32 shell = 1;

        while (shell < (set.Count / 3)) shell = shell * 3 + 1;

        while (shell >= 1) {
            for (Int32 index = shell; index < set.Count; index++) {
                for (Int32 insertion = index; insertion >= shell && set[insertion - shell].CompareTo(set[insertion]) > 0; insertion -= shell) {
                    Swap(set, insertion - shell, insertion);
                }
            }

            shell = shell / 3;
        }

        return set;
    }

    public static IList<T> QuickSort<T>(this IList<T> set)
        where T : IComparable<T> {
        return QuickSort<T>(set, 0, set.Count - 1);
    }
}

并且,以下是您如何使用它:

public static void Main() {
    List<Int32> numbers = new List<int> { 1, 3, 2, 4, 2 };

    foreach (Int32 number in numbers.QuickSort())
        Console.WriteLine(number);

    Console.ReadLine();
}

答案 1 :(得分:2)

如果你确实需要这样的话,这样的事情应该可以解决问题。

public static class Extensions
{
    public static void InPlaceSort(this IList list)
    {
        var sortedItems = new object[list.Count];
        for (int i = 0; i < list.Count; ++i)
        {
            sortedItems[i] = list[i];
        }
        Array.Sort(sortedItems);
        for (int i = 0; i < list.Count; ++i)
        {
            list[i] = sortedItems[i];
        }
    }
}


IList list = new[] { 3,1,2 };
list.InPlaceSort(); // { 1, 2, 3 }

list = new List<int>(new[] { 4, 2, 3 });
list.InPlaceSort(); // List<int> { 2, 3, 4 }

如果您使用的是IList<T>而不只是IList,那么您可以节省前几行并执行以下操作:

var sortedItems = list.OrderBy(x => x).ToArray();

你仍然需要最后的简单循环将它们放回原始集合中。

答案 2 :(得分:1)

没有。使用IEnumerable.OrderBy()SortedList<T>,这两个都会创建新的集合。问题是为什么你不能创建一个新的集合?

答案 3 :(得分:0)

通过保持简单并使用.NET的内置排序(也允许自定义IComparer s

来扩展方法解决方案的另一种看法
public static class IListExtensions
{
    public static void Sort<T>(this IList<T> list)
    {
        var orderedList = list.OrderBy(i => i).ToArray();

        for( int i = 0; i < list.Count; ++i )
        {
            list[i] = orderedList[i];
        }
    }

    public static void Sort<T>(this IList<T> list, IComparer<T> comparer )
    {
        var orderedList = list.OrderBy(i => i, comparer).ToArray();

        for (int i = 0; i < list.Count; ++i)
        {
            list[i] = orderedList[i];
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var orig = new List<int>() { 2, 3, 1 };
        var toOrder = orig;

        Console.Write("Orig: ");
        orig.ForEach(i => Console.Write("{0} ", i));
        toOrder.Sort();
        Console.Write("\nOrdered: ");
        toOrder.ForEach(i => Console.Write("{0} ", i));
        Console.Write("\nOrig: ");
        orig.ForEach(i => Console.Write("{0} ", i));


        Console.ReadLine();
    }

}