Как отсортировать список <T>по свойству объекта - PullRequest
1081 голосов
/ 22 июля 2010

У меня есть класс с именем Order, который имеет такие свойства, как OrderId, OrderDate, Quantity и Total. У меня есть список этого Order класса:

List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders

Теперь я хочу отсортировать список на основе одного свойства объекта Order, например, мне нужно отсортировать его по дате заказа или идентификатору заказа.

Как я могу сделать это в C #?

Ответы [ 19 ]

1576 голосов
/ 22 июля 2010

Самый простой способ, который я могу придумать, это использовать Linq:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
652 голосов
/ 22 июля 2010

Если вам нужно отсортировать список на месте, вы можете использовать метод Sort, передавая делегат Comparison<T>:

objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));

Если вы предпочитаете создавать новую, отсортированную последовательность, а не сортировать на месте, вы можете использовать метод LINQ OrderBy, как упоминалось в других ответах.

207 голосов
/ 22 июля 2010

Для этого без LINQ на .Net2.0:

List<Order> objListOrder = GetOrderList();
objListOrder.Sort(
    delegate(Order p1, Order p2)
    {
        return p1.OrderDate.CompareTo(p2.OrderDate);
    }
);

Если вы используете .Net3.0, тогда ответ ЛукиХа - это то, что вам нужно.

Для сортировки по нескольким свойствам вы все равно можете делать это в делегате. Например:

orderList.Sort(
    delegate(Order p1, Order p2)
    {
        int compareDate = p1.Date.CompareTo(p2.Date);
        if (compareDate == 0)
        {
            return p2.OrderID.CompareTo(p1.OrderID);
        }
        return compareDate;
    }
);

Это даст вам по возрастанию даты с по убыванию порядковые номера.

Однако я бы не рекомендовал прикреплять делегатов, так как это будет означать много мест без повторного использования кода. Вы должны реализовать IComparer и просто передать это своему Sort методу. См. здесь .

public class MyOrderingClass : IComparer<Order>
{
    public int Compare(Order x, Order y)
    {
        int compareDate = x.Date.CompareTo(y.Date);
        if (compareDate == 0)
        {
            return x.OrderID.CompareTo(y.OrderID);
        }
        return compareDate;
    }
}

А затем, чтобы использовать этот класс IComparer, просто создайте его экземпляр и передайте его в метод Sort:

IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);
95 голосов
/ 22 июля 2010

Самый простой способ заказать список - использовать OrderBy

 List<Order> objListOrder = 
    source.OrderBy(order => order.OrderDate).ToList();

Если вы хотите упорядочить по нескольким столбцам, например, следующим SQL-запросом.

ORDER BY OrderDate, OrderId

Для этого вам нужноможно использовать ThenBy, как показано ниже.

  List<Order> objListOrder = 
    source.OrderBy(order => order.OrderDate).ThenBy(order => order.OrderId).ToList();
32 голосов
/ 22 июля 2010

Делаем это без Linq, как вы сказали:

public class Order : IComparable
{
    public DateTime OrderDate { get; set; }
    public int OrderId { get; set; }

    public int CompareTo(object obj)
    {
        Order orderToCompare = obj as Order;
        if (orderToCompare.OrderDate < OrderDate || orderToCompare.OrderId < OrderId)
        {
            return 1;
        }
        if (orderToCompare.OrderDate > OrderDate || orderToCompare.OrderId > OrderId)
        {
            return -1;
        }

        // The orders are equivalent.
        return 0;
    }
}

Затем просто вызовите .sort () в вашем списке заказов

23 голосов
/ 16 октября 2014

Классическое объектно-ориентированное решение

Сначала я должен понять удивительность LINQ .... Теперь, когда мы получили это с пути

Вариация на ответ Джимми Хоффа.С обобщениями параметр CompareTo становится безопасным для типа.

public class Order : IComparable<Order> {

    public int CompareTo( Order that ) {
        if ( that == null ) return 1;
        if ( this.OrderDate > that.OrderDate) return 1;
        if ( this.OrderDate < that.OrderDate) return -1;
        return 0;
    }
}

// in the client code
// assume myOrders is a populated List<Order>
myOrders.Sort(); 

Эта сортируемость по умолчанию, конечно, может использоваться повторно.То есть каждому клиенту не нужно избыточно переписывать логику сортировки.Обмен «1» и «-1» (или логические операторы по вашему выбору) меняет порядок сортировки.

18 голосов
/ 13 июня 2013

// Полностью универсальная сортировка для использования с сеткой

public List<T> Sort_List<T>(string sortDirection, string sortExpression, List<T> data)
    {

        List<T> data_sorted = new List<T>();

        if (sortDirection == "Ascending")
        {
            data_sorted = (from n in data
                              orderby GetDynamicSortProperty(n, sortExpression) ascending
                              select n).ToList();
        }
        else if (sortDirection == "Descending")
        {
            data_sorted = (from n in data
                              orderby GetDynamicSortProperty(n, sortExpression) descending
                              select n).ToList();

        }

        return data_sorted;

    }

    public object GetDynamicSortProperty(object item, string propName)
    {
        //Use reflection to get order type
        return item.GetType().GetProperty(propName).GetValue(item, null);
    }
5 голосов
/ 14 февраля 2014

Вот общий метод расширения LINQ, который не создает дополнительную копию списка:

public static void Sort<T,U>(this List<T> list, Func<T, U> expression)
    where U : IComparable<U>
{
    list.Sort((x, y) => expression.Invoke(x).CompareTo(expression.Invoke(y)));
}

Чтобы использовать его:

myList.Sort(x=> x.myProperty);

Недавно я создал этот дополнительный, которыйпринимает ICompare<U>, так что вы можете настроить сравнение.Это пригодилось, когда мне нужно было выполнить сортировку строк Natural:

public static void Sort<T, U>(this List<T> list, Func<T, U> expression, IComparer<U> comparer)
    where U : IComparable<U>
{    
    list.Sort((x, y) => comparer.Compare(expression.Invoke(x), expression.Invoke(y)));
}
4 голосов
/ 22 июля 2010

Использование LINQ

objListOrder = GetOrderList()
                   .OrderBy(o => o.OrderDate)
                   .ToList();

objListOrder = GetOrderList()
                   .OrderBy(o => o.OrderId)
                   .ToList();
3 голосов
/ 24 ноября 2011
//Get data from database, then sort list by staff name:

List<StaffMember> staffList = staffHandler.GetStaffMembers();

var sortedList = from staffmember in staffList
                 orderby staffmember.Name ascending
                 select staffmember;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...