Cómo Ordenar una Lista por una propiedad en el objeto
Tengo una clase llamada Order
, que tiene propiedades tales como OrderId
, OrderDate
, Quantity
, y Total
. Tengo una lista de esta clase Order
:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
Ahora quiero ordenar la lista en función de una propiedad del objeto Order
, por ejemplo, necesito ordenarla por la fecha de la orden o el id de la orden.
¿Cómo puedo hacer esto en C#?
19 answers
La forma más fácil que se me ocurre es usar Linq:
List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-20 20:54:49
Si necesita ordenar la lista en su lugar, puede usar el Sort
método, pasando una Comparison<T>
delegado:
objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));
Si prefiere crear una nueva secuencia ordenada en lugar de ordenar en el lugar, puede usar la secuencia de LINQ OrderBy
método, como se mencionó en las otras respuestas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 13:28:33
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 la respuesta de LukeH es lo que buscas.
Para ordenar en varias propiedades, todavía 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 fechas ascendentescon ordenidas descendentes.
Sin embargo, no recomendaría pegar delegados, ya que significará muchos lugares sin reutilización de código. Debe implementar un IComparer
y simplemente pasar eso a través de su método Sort
. Véase 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 IComparer, simplemente instanciala y pásala a tu método Sort:
IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:29
La forma más sencilla de ordenar una lista es usar OrderBy
List<Order> objListOrder =
source.OrderBy(order => order.OrderDate).ToList();
Si desea ordenar por varias columnas como la siguiente consulta SQL.
ORDER BY OrderDate, OrderId
Para lograr esto puedes usar ThenBy
como sigue.
List<Order> objListOrder =
source.OrderBy(order => order.OrderDate).ThenBy(order => order.OrderId).ToList();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-13 07:41:39
Hacerlo 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;
}
}
Entonces solo llama .sort() en su lista de Pedidos
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-30 16:36:40
Una Solución Clásica Orientada a Objetos
Primero debo arrodillarme ante la genuflexión de LINQ.... Ahora que tenemos que fuera del camino
Una variación de la respuesta de JimmyHoffa. Con genéricos el parámetro CompareTo
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 capacidad de clasificación predeterminada es reutilizable, por supuesto. Es decir, cada cliente no tiene que reescribir redundantemente la lógica de ordenación. Intercambiar el "1" y " -1 " (o los operadores lógicos, su elección) invierte el orden de clasificación.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-11 05:41:48
/ / Clasificación totalmente genérica para usar con un gridview
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-13 01:37:08
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 un ICompare<U>
, para que pueda personalizar la comparación. Esto me resultó útil cuando necesitaba hacer una ordenación natural de cadenas:
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)));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-08 21:06:09
Usando LINQ
objListOrder = GetOrderList()
.OrderBy(o => o.OrderDate)
.ToList();
objListOrder = GetOrderList()
.OrderBy(o => o.OrderId)
.ToList();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 13:16:27
//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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-23 21:51:44
Una mejora de la versión de Roger.
El problema con GetDynamicSortProperty es que solo obtiene los nombres de las propiedades, pero ¿qué sucede si en GridView usamos NavigationProperties? enviará una excepción, ya que encuentra null.
Ejemplo:
"Employee.Company.Name;" will crash... since permite solo "Name" como parámetro para obtener su valor.
Esta es una versión mejorada que nos permite ordenar por Propiedades de navegación.
public object GetDynamicSortProperty(object item, string propName)
{
try
{
string[] prop = propName.Split('.');
//Use reflection to get order type
int i = 0;
while (i < prop.Count())
{
item = item.GetType().GetProperty(prop[i]).GetValue(item, null);
i++;
}
return item;
}
catch (Exception ex)
{
throw ex;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-04 14:32:52
Puede hacer algo más genérico sobre la selección de propiedades, pero sea específico sobre el tipo que está seleccionando, en su caso 'Order':
Escribe tu función como genérica:
public List<Order> GetOrderList<T>(IEnumerable<Order> orders, Func<Order, T> propertySelector)
{
return (from order in orders
orderby propertySelector(order)
select order).ToList();
}
Y luego úsalo así:
var ordersOrderedByDate = GetOrderList(orders, x => x.OrderDate);
Puede ser aún más genérico y definir un tipo abierto para lo que desea ordenar:
public List<T> OrderBy<T,P>(IEnumerable<T> collection, Func<T,P> propertySelector)
{
return (from item in collection
orderby propertySelector(item)
select item).ToList();
}
Y úsalo de la misma manera:
var ordersOrderedByDate = OrderBy(orders, x => x.OrderDate);
Que es una forma compleja e innecesaria de hacer un estilo LINQ 'OrderBy', Pero puede darte un pista de cómo se puede implementar de manera genérica
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-02 10:26:08
Por favor, permítanme completar la respuesta de @ LukeH con un código de ejemplo, ya que lo he probado Creo que puede ser útil para algunos:
public class Order
{
public string OrderId { get; set; }
public DateTime OrderDate { get; set; }
public int Quantity { get; set; }
public int Total { get; set; }
public Order(string orderId, DateTime orderDate, int quantity, int total)
{
OrderId = orderId;
OrderDate = orderDate;
Quantity = quantity;
Total = total;
}
}
public void SampleDataAndTest()
{
List<Order> objListOrder = new List<Order>();
objListOrder.Add(new Order("tu me paulo ", Convert.ToDateTime("01/06/2016"), 1, 44));
objListOrder.Add(new Order("ante laudabas", Convert.ToDateTime("02/05/2016"), 2, 55));
objListOrder.Add(new Order("ad ordinem ", Convert.ToDateTime("03/04/2016"), 5, 66));
objListOrder.Add(new Order("collocationem ", Convert.ToDateTime("04/03/2016"), 9, 77));
objListOrder.Add(new Order("que rerum ac ", Convert.ToDateTime("05/02/2016"), 10, 65));
objListOrder.Add(new Order("locorum ; cuius", Convert.ToDateTime("06/01/2016"), 1, 343));
Console.WriteLine("Sort the list by date ascending:");
objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));
foreach (Order o in objListOrder)
Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
Console.WriteLine("Sort the list by date descending:");
objListOrder.Sort((x, y) => y.OrderDate.CompareTo(x.OrderDate));
foreach (Order o in objListOrder)
Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
Console.WriteLine("Sort the list by OrderId ascending:");
objListOrder.Sort((x, y) => x.OrderId.CompareTo(y.OrderId));
foreach (Order o in objListOrder)
Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
//etc ...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-19 10:18:06
Ninguna de las respuestas anteriores eran lo suficientemente genéricas para mí, así que hice esta:
var someUserInputStringValue = "propertyNameOfObject i.e. 'Quantity' or 'Date'";
var SortedData = DataToBeSorted
.OrderBy(m => m.GetType()
.GetProperties()
.First(n =>
n.Name == someUserInputStringValue)
.GetValue(m, null))
.ToList();
Cuidado con los conjuntos de datos masivos. Es easy code, pero podría meterte en problemas si la colección es enorme y el tipo de objeto de la colección tiene un gran número de campos. El tiempo de ejecución es NxM donde:
N = # de elementos en la colección
M = # de propiedades dentro del objeto
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-22 18:45:36
var obj = db.Items.Where...
var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-31 08:26:36
Hacer uso de LiNQ OrderBy
List<Order> objListOrder=new List<Order> ();
objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 13:16:31
Basado en el comparador de GenericTypeTea:
podemos obtener más flexibilidad agregando banderas de clasificación:
public class MyOrderingClass : IComparer<Order> {
public int Compare(Order x, Order y) {
int compareDate = x.Date.CompareTo(y.Date);
if (compareDate == 0) {
int compareOrderId = x.OrderID.CompareTo(y.OrderID);
if (OrderIdDescending) {
compareOrderId = -compareOrderId;
}
return compareOrderId;
}
if (DateDescending) {
compareDate = -compareDate;
}
return compareDate;
}
public bool DateDescending { get; set; }
public bool OrderIdDescending { get; set; }
}
En este escenario, debe crear una instancia como MyOrderingClass explícitamente( en lugar de IComparer )
para establecer sus propiedades de ordenación :
MyOrderingClass comparer = new MyOrderingClass();
comparer.DateDescending = ...;
comparer.OrderIdDescending = ...;
orderList.Sort(comparer);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-06 14:05:49
Desde el punto de vista del rendimiento, lo mejor es usar una lista ordenada para que los datos se ordenen a medida que se agregan al resultado. Otros enfoques necesitan al menos una iteración adicional en los datos y la mayoría crean una copia de los datos, por lo que no solo el rendimiento sino el uso de memoria también se verán afectados. Puede que no sea un problema con un par de cientos de elementos, pero lo será con miles, especialmente en servicios donde muchas solicitudes simultáneas pueden ordenar al mismo tiempo. Echa un vistazo al Sistema.Colecciones.Espacio de nombres genérico y elija una clase con clasificación en lugar de Lista.
Y evitar implementaciones genéricas usando reflexión cuando sea posible, esto también puede causar problemas de rendimiento.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-31 11:53:17
Cualquiera que trabaje con tipos nullables, Value
debe usar CompareTo
.
objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-19 15:35:41