Pregunta Cómo ordenar una lista por una propiedad en el objeto


Tengo una clase llamada Order que tiene propiedades tales como OrderId, OrderDate, Quantityy Total. Tengo una lista de esto Order clase:

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

Ahora quiero ordenar la lista basada en una propiedad de Order objeto, por ejemplo, necesito ordenarlo por la fecha del pedido o por el ID del pedido.

¿Cómo puedo hacer esto en C #?


902
2017-07-22 13:13


origen


Respuestas:


La forma más fácil que puedo pensar es usar Linq:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();

1328
2017-07-22 13:16



Si necesita ordenar la lista en el lugar, puede usar la Sort método, pasando un Comparison<T> delegar:

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

Si prefiere crear una secuencia nueva y ordenada en lugar de ordenarla en el lugar, puede usar LINQ's OrderBy método, como se menciona en las otras respuestas.


501
2017-07-22 13:23



Para hacer esto sin LINQ en .Net2.0:

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

Si estás en .Net3.0, entonces LukeH responder es lo que buscas

Para ordenar múltiples propiedades, puede hacerlo dentro de un delegado. Por ejemplo:

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;
    }
);

Esto te daría ascendiendo fechas con descendiendo orderIds.

Sin embargo, no recomendaría pegar delegados ya que significará muchos lugares sin reutilización de código. Deberías implementar un IComparer y solo pasa eso a tu Sort método. Ver aquí.

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;
    }
}

Y luego, para usar esta clase de IComparer, simplemente ejemplínelo y páselo a su método Sort:

IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);

197
2017-07-22 13:35



La manera más simple de pedir una lista es usar OrderBy

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

Si desea realizar un pedido por varias columnas, como la siguiente consulta SQL.

ORDER BY OrderDate, OrderId

Para lograr esto, puede usar ThenBy como siguiendo.

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

76
2017-07-22 13:23



Haciéndolo sin Linq como dijiste:

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;
    }
}

Luego solo llame a .sort () en su lista de pedidos


31
2017-07-22 13:55



Una solución orientada a objetos clásica

Primero debo arrodillarme ante la genialidad de LINQ ... Ahora que lo tenemos todo fuera del camino

Una variación en la respuesta de JimmyHoffa. Con genéricos el CompareTo parámetro se convierte en tipo seguro.

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(); 

Esta clasificación predeterminada es reutilizable, por supuesto. Es decir, cada cliente no tiene que volver a escribir de forma redundante la lógica de clasificación. Al intercambiar el "1" y "-1" (o los operadores lógicos, su elección) invierte el orden de clasificación.


19
2017-10-16 14:03



// Clasificación totalmente genérica para usar con una vista de grilla

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);
    }

15
2018-06-13 01:37



Aquí hay un método genérico de extensión LINQ que no crea una copia adicional de la lista:

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)));
}

Para usarlo:

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

Recientemente construí este adicional que acepta una ICompare<U>, para que pueda personalizar la comparación. Esto fue útil cuando tuve que hacer una secuencia de cuerda 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)));
}

5
2018-02-14 14:25



Usando LINQ

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

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

3
2017-07-22 13:16



//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;

3
2017-11-23 21:42