varios una sort por ordenar objetos numeros mostrar listas lista elementos descendente con campos arreglo c# generics list sorting

una - ordenar numeros de un arreglo en c#



Cómo ordenar una lista<T> por una propiedad en el objeto (19)

Tengo una clase llamada Order que tiene propiedades como OrderId , OrderDate , Quantity y Total . Tengo una lista de esta clase de 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 fecha de pedido o ID de pedido.

¿Cómo puedo hacer esto en C #?


// Clasificación totalmente genérica para usar con una vista de cuadrícula

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


Aquí hay un método de extensión LINQ genérico 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í esta ICompare<U> adicional que acepta un ICompare<U> , para que pueda personalizar la comparación. Esto fue útil cuando necesité hacer un ordenamiento natural de cuerdas:

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


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 explícita como MyOrderingClass (en lugar de IComparer )
Para establecer sus propiedades de clasificación:

MyOrderingClass comparer = new MyOrderingClass(); comparer.DateDescending = ...; comparer.OrderIdDescending = ...; orderList.Sort(comparer);


Cualquiera que trabaje con tipos anulables, se requiere un valor para usar CompareTo .

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


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 crea una copia de los datos, por lo que no solo se verá afectado el rendimiento sino también el uso de la memoria. Puede que no sea un problema con un par de cientos de elementos, pero sí con miles, especialmente en servicios donde muchas solicitudes simultáneas pueden ordenarse al mismo tiempo. Eche un vistazo a System.Collections.Generic namespace y elija una clase con clasificación en lugar de Lista.

Y evite implementaciones genéricas utilizando reflexión cuando sea posible, esto también puede causar problemas de rendimiento.


Hacer uso de LiNQ OrderBy

List<Order> objListOrder=new List<Order> (); objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();


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


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

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


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 sigue la consulta SQL.

ORDER BY OrderDate, OrderId

Para lograr esto puedes usar ThenBy como siguiente.

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


Ninguna de las respuestas anteriores fue lo suficientemente genérica 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 sin embargo. Es un código fácil, pero podría causarle problemas si la colección es enorme y el tipo de objeto de la colección tiene una gran cantidad de campos. El tiempo de ejecución es NxM donde:

N = # de elementos en la colección

M = # de propiedades dentro del objeto


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 answer de LukeH es lo que estás buscando.

Para ordenar en múltiples 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 le daría fechas ascendentes con órdenes de orden descendentes .

Sin embargo, no recomendaría pegar delegados ya que significará muchos lugares sin la reutilización del código. Debe implementar un IComparer y simplemente pasarlo a su método de Sort . Ver here

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 cree una instancia y pásela a su método de clasificación:

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


Permítame completar la respuesta de @LukeH con un código de ejemplo, ya que la 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 ... }


Puede hacer algo más genérico sobre la selección de propiedades, pero ser específico sobre el tipo que está seleccionando, en su caso ''Orden'':

escribe tu función como una 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 usarlo así:

var ordersOrderedByDate = GetOrderList(orders, x => x.OrderDate);

Puede ser aún más genérico y definir un tipo abierto para lo que quiere 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 usalo de la misma manera:

var ordersOrderedByDate = OrderBy(orders, x => x.OrderDate);

Esta es una forma compleja e innecesaria de hacer un estilo LINQ ''OrderBy'', pero puede darle una idea de cómo se puede implementar de una manera genérica.


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

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

Si prefiere crear una nueva secuencia ordenada en lugar de una ordenación en el lugar, puede usar el método OrderBy de LINQ, como se menciona en las otras respuestas.


Una versión mejorada de Roger.

El problema con GetDynamicSortProperty es que solo se obtienen los nombres de las propiedades, pero ¿qué sucede si en GridView usamos NavigationProperties? Enviará una excepción, ya que encuentra nula.

Ejemplo:

"Employee.Company.Name;" se bloqueará ... ya que solo permite "Name" como parámetro para obtener su valor.

Aquí hay 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; } }


Usando LINQ

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


Una solución clásica orientada a objetos

Primero debo hacer una genuflexión a la genialidad de LINQ ... Ahora que lo hemos dejado de lado

Una variación en la respuesta de JimmyHoffa. Con los genéricos, el parámetro CompareTo se vuelve de 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 ordenabilidad por defecto es reutilizable, por supuesto. Es decir, cada cliente no tiene que volver a escribir de forma redundante la lógica de clasificación. Cambiar el "1" y el "-1" (o los operadores lógicos, su elección) invierte el orden de clasificación.


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


var obj = db.Items.Where... var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));