How Do I Sort IList<Class>?

混江龙づ霸主 提交于 2020-08-19 06:16:19

问题


There's no Sort() function for IList. Can someoene help me with this? I want to sort my own IList.

Suppose this is my IList:

public class MyObject() 
{
 public int number { get; set; }
 public string marker { get; set; }
}

How do I sort myobj using the marker string?

public void SortObject()
{
 IList<MyObject> myobj = new List<MyObject>();
}

回答1:


Use OrderBy

Example

public class MyObject() 
{
    public int number { get; set; }
    public string marker { get; set; }
}

IList<MyObject> myobj = new List<MyObject>();
var orderedList = myobj.OrderBy(x => x.marker).ToList();

For a case insensitive you should use a IComparer

public class CaseInsensitiveComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
    }
}

IList<MyObject> myobj = new List<MyObject>();
var orderedList = myobj.OrderBy(x => x.marker, new CaseInsensitiveComparer()).ToList();



回答2:


I would go against using OrderBy with a list because it's a LINQ extension method, therefore:

  • It wraps the list in an enumerable, then enumerates it and fills a new temporary list, then sorts this new list.
  • It wraps the sorted list inside another enumerable.
  • Then when you call ToList(), it iterates on it and fills another new list with the items.

In essence: it creates and fills 2 new lists and 2 enumerables in addition to the actual sorting. In comparison, List.Sort() sorts in place and create nothing so it's way more efficient.

My recommendation would be:

  • If you know the underlying type, use List.Sort() or Array.Sort(array)
  • If you don't know the underlying type, copy the List to a temporary array and sort it using Array.Sort(array) and return it.



回答3:


var sorted = myObj.OrderBy(x => x.marker);



回答4:


OrderBy definitely gets the job done, but I personally prefer the syntax of List.Sort because you can feed it a Comparison<T> delegate instead of having to write a class that implements IComparer<T>. We can accomplish that goal with an extension method, and if that's something you're interested in, check out SortExtensions:

http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/




回答5:


For explanation why not to use OrderBy or similar check Christophe's answer.

Here is one attempt to make fast Sort:

public static void Sort<T>(this IList<T> ilist)
{
    switch(ilist)
    {
        case List<T> lst:
            lst.Sort();
            break;
        case Array arr:
            Array.Sort(arr);
            break;
        default:
            throw new NotImplementedException();
            // or add slow impl if you don't want this to fail!!
    }
}



回答6:


To sort in-place you would essentially see these two approaches:

        IList<T> list = .... // your ilist
        var sorted = list.ToArray();
        Array.Sort(sorted);

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

and

        IList<T> list = .... // your ilist
        ArrayList.Adapter((IList)list).Sort();

The second one might look simpler but won't be great for value type collections since it incur boxing penalties. Furthermore there is no guarantee your IList<T> will be implementing IList. First one is better IMO.


You can also use the second approach to sort an ICollection<T> in-place but it is questionable if you should expose such a functionality since ICollection<T> contract doesn't guarantee an order (think hash structures). Anyway to show you code example:

    ICollection<T> collection = .... // your icollection
    var sorted = collection.ToArray();
    Array.Sort(sorted);

    collection.Clear();
    foreach (var i in sorted)
    {
       collection.Add(i);
    }

A note on sort stability, .NET's Array/List sorting algorithms are unstable. For a stable sort you will have to use:

        IList<T> list = .... // your ilist
        var sorted = list.OrderBy(i => i).ToArray();

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

This can't be as fast as unstable sorts.


Finally, for a complete answer, perhaps a composite approach taken by watbywbarif is better:

// In-place but unstable sort.
public static void Sort<T>(this IList<T> ilist, /* pass in your comparers here */)
{
    switch(ilist)
    {
        case List<T> list:
            list.Sort();
            break;

        case T[] array:
            Array.Sort(array);
            break;

        default:
            var sorted = ilist.ToArray();
            sorted.Sort();

            for (int i = 0; i < ilist.Count; i++)
            {
                ilist[i] = sorted[i];
            } 
                    
            break;
    }
}

That's as far as built-in approaches go. For faster implemenation you will have to roll out your own, see: https://stackoverflow.com/a/19167475



来源:https://stackoverflow.com/questions/3844463/how-do-i-sort-ilistclass

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!