Tengo una clase llamada Order
que tiene propiedades tales como OrderId
, OrderDate
, Quantity
, y Total
. Tengo una lista de esta Order
clase:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
Ahora quiero ordenar la lista en función de una propiedad del Order
objeto, por ejemplo, necesito ordenarla por la fecha del pedido o el ID del pedido.
¿Cómo puedo hacer esto en C #?
Respuestas:
La forma más fácil que se me ocurre es usar Linq:
fuente
listWithObjects = listWithObjects.OrderByDescending(o => o.Status).ToList();
suficiente para tal esfuerzo?Si necesita ordenar la lista en el lugar, puede usar el
Sort
método, pasando unComparison<T>
delegado:Si prefiere crear una nueva secuencia ordenada en lugar de ordenar en el lugar, puede usar el
OrderBy
método de LINQ , como se menciona en las otras respuestas.fuente
x
yy
en el lado derecho de la flecha=>
.Nullable<>
(tomeDateTime?
como ejemplo) puede usar el.Sort((x, y) => Nullable.Compare(x.OrderDate, y.OrderDate))
cual tratará nulo como precedente a todos los valores no nulos. Es exactamente lo mismo que.Sort((x, y) => Comparer<DateTime?>.Default.Compare(x.OrderDate, y.OrderDate)
.Para hacer esto sin LINQ en .Net2.0:
Si estás en .Net3.0, entonces la respuesta de LukeH es lo que buscas.
Para ordenar múltiples propiedades, aún puede hacerlo dentro de un delegado. Por ejemplo:
Esto le daría fechas ascendentes con órdenes descendentes .
Sin embargo, no recomendaría delegar a los delegados, ya que significará muchos lugares sin reutilización de código. Debe implementar un
IComparer
y simplemente pasarlo a suSort
método. Ver aquí .Y luego, para usar esta clase de IComparer, simplemente ejemplifique y pase a su método Sort:
fuente
IComparer
implementaciones, dándonos un comportamiento polimórfico.La manera más simple de ordenar una lista es usar
OrderBy
Si desea ordenar por varias columnas como seguir la consulta SQL.
Para lograr esto, puede usar lo
ThenBy
siguiente.fuente
Haciéndolo sin Linq como dijiste:
Luego simplemente llame a .sort () en su lista de Órdenes
fuente
null
en elas
elenco. De eso se trataas
, ya que (ja, ja)(Order)obj
lanza una excepción cuando falla.if(orderToCompare == null) return 1;
.as
vuelvenull
si el elenco falla. Pero al menos la prueba nula es correcta.List<Order>
debe garantizarse que el tipo coincida en elas
2014, por lo que probablemente no escribió un error, tanto como para evitar una declaración de guardia innecesaria :)List<Order>
; pero tú y yo nos hemos encontrado con el programadorUna solución clásica orientada a objetos
Primero debo hacer una genuflexión a la genialidad de LINQ ... Ahora que lo hemos quitado del camino
Una variación de la respuesta JimmyHoffa. Con los genéricos, el
CompareTo
parámetro se convierte en tipo seguro.Esta capacidad de 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. Intercambiar el "1" y el "-1" (o los operadores lógicos, según su elección) invierte el orden de clasificación.
fuente
this
objeto es mayor que nulo. Para fines de clasificación, una referencia de objeto nulo "es menor que"this
objeto. Así es como decidí definir cómo se ordenarán los nulos.// Clasificación totalmente genérica para usar con una vista de cuadrícula
fuente
data.OrderBy()
. Un poco más fácil que reinventar la rueda.Aquí hay un método genérico de extensión LINQ que no crea una copia adicional de la lista:
Para usarlo:
Recientemente construí este adicional que acepta un
ICompare<U>
, para que pueda personalizar la comparación. Esto fue útil cuando necesitaba hacer un tipo de cadena natural:fuente
OrderBy
hace todo eso internamente.void
método de extensión con este espíritu:static class Extensions { public static void SortBy<TSource, TKey>(this List<TSource> self, Func<TSource, TKey> keySelector) { self.SortBy(keySelector, Comparer<TKey>.Default); } public static void SortBy<TSource, TKey>(this List<TSource> self, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) { self.Sort((x, y) => comparer.Compare(keySelector(x), keySelector(y))); } }
puede complementarse con unSortByDescending
método. ¡Los comentarios de @ Servy también se aplican a mi código!Usando LINQ
fuente
fuente
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 nulo.
Ejemplo:
"Employee.Company.Name;" se bloqueará ... ya que solo permite que "Nombre" como parámetro obtenga su valor.
Aquí hay una versión mejorada que nos permite ordenar por propiedades de navegación.
fuente
Puede hacer algo más genérico con respecto a la selección de propiedades y ser específico sobre el tipo de que está seleccionando, en su caso 'Pedido':
escribe tu función como genérica:
y luego úsalo así:
Puede ser aún más genérico y definir un tipo abierto para lo que desea pedir:
y úsalo de la misma manera:
Lo cual es una forma estúpida e innecesaria y compleja de hacer un estilo LINQ 'OrderBy', pero puede darle una idea de cómo se puede implementar de manera genérica
fuente
Permítanme completar la respuesta de @LukeH con un código de muestra, ya que lo he probado y creo que puede ser útil para algunos:
fuente
fuente
Haz uso de LiNQ
OrderBy
fuente
Basado en GenericTypeTea 's Comparer:
podemos obtener más flexibilidad agregando banderas de clasificación:
En este escenario, debe crear una instancia explícita como MyOrderingClass (en lugar de IComparer )
para establecer sus propiedades de clasificación:
fuente
Ninguna de las respuestas anteriores fue lo suficientemente genérica para mí, así que hice esta:
Sin embargo, tenga cuidado con los conjuntos de datos masivos. Es un código fácil, pero podría meterte en 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
fuente
Cualquier persona que trabaje con tipos anulables
Value
debe usarCompareTo
.objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));
fuente
Desde el punto de vista del rendimiento, lo mejor es usar una lista ordenada para que los datos se clasifiquen 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 el rendimiento sino el uso de la 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 en los que muchas solicitudes concurrentes pueden ordenar al mismo tiempo. Eche un vistazo a System.Collections.Generic namespace y elija una clase con clasificación en lugar de List.
Y evite implementaciones genéricas utilizando la reflexión cuando sea posible, esto también puede causar problemas de rendimiento.
fuente
Supongamos que tiene el siguiente código, en este código, tenemos una clase Passenger con un par de propiedades en las que queremos clasificar según.
Para que pueda implementar su estructura de clasificación utilizando el delegado de composición.
fuente