Eu tenho uma classe chamada Order
que tem propriedades tais como OrderId
, OrderDate
, Quantity
, e Total
. Eu tenho uma lista desta Order
classe:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
Agora, quero classificar a lista com base em uma propriedade do Order
objeto, por exemplo, preciso classificá-la pela data do pedido ou pelo ID do pedido.
Como posso fazer isso em c #?
Respostas:
A maneira mais fácil de pensar é usar o Linq:
fonte
listWithObjects = listWithObjects.OrderByDescending(o => o.Status).ToList();
suficiente para tal empreendimento?Se você precisar classificar a lista no local, poderá usar o
Sort
método, passando umComparison<T>
delegado:Se você preferir criar uma nova seqüência classificada, em vez de classificar no local, poderá usar o
OrderBy
método LINQ , conforme mencionado nas outras respostas.fonte
x
ey
no lado direito da seta=>
.Nullable<>
(considereDateTime?
o exemplo), você pode usar o.Sort((x, y) => Nullable.Compare(x.OrderDate, y.OrderDate))
que tratará nulo como precedendo todos os valores não nulos. É exatamente o mesmo que.Sort((x, y) => Comparer<DateTime?>.Default.Compare(x.OrderDate, y.OrderDate)
.Para fazer isso sem o LINQ no .Net2.0:
Se você está no .Net3.0, a resposta de LukeH é o que você procura .
Para classificar em várias propriedades, você ainda pode fazê-lo em um delegado. Por exemplo:
Isso forneceria datas ascendentes com orderIds decrescente .
No entanto, eu não recomendaria a adesão de delegados, pois isso significa muitos lugares sem reutilização de código. Você deve implementar
IComparer
e passar isso ao seuSort
método. Veja aqui .E então, para usar essa classe IComparer, instancie-a e passe-a para o seu método Sort:
fonte
IComparer
implementações, dando-nos um comportamento polimórfico.A maneira mais simples de solicitar uma lista é usar
OrderBy
Se você deseja solicitar várias colunas, como segue a Consulta SQL.
Para conseguir isso, você pode usar o
ThenBy
seguinte.fonte
Fazendo isso sem o Linq, como você disse:
Em seguida, basta chamar .sort () na sua lista de pedidos
fonte
null
noas
elenco. Qual é o objetivo deas
, pois (ha, ha)(Order)obj
lança uma exceção quando falha.if(orderToCompare == null) return 1;
.as
retornanull
se o elenco falhar. Mas pelo menos o teste nulo está certo.List<Order>
a garantia de que o tipo corresponda no ano deas
2014. Você provavelmente não escreveu um bug, além de evitar uma declaração de guarda desnecessária :)List<Order>
; mas você e eu conheci o programador auto-encapsulado que é presunção tácita é "eu estou escrevendo este código para que ele não será errado usado"Uma solução clássica orientada a objetos
Primeiro, devo me associar à grandiosidade do LINQ .... Agora que temos isso fora do caminho
Uma variação na resposta JimmyHoffa. Com genéricos, o
CompareTo
parâmetro passa a ser do tipo seguro.Essa classificação padrão é reutilizável, é claro. Ou seja, cada cliente não precisa redundantemente reescrever a lógica de classificação. Trocar o "1" e o "-1" (ou os operadores lógicos, sua escolha) reverte a ordem de classificação.
fonte
this
objeto é maior que nulo. Para fins de classificação, uma referência de objeto nulo "é menor que"this
objeto. Foi assim que decidi definir como os nulos serão classificados.// Classificação totalmente genérica para uso com um gridview
fonte
data.OrderBy()
. Um pouco mais fácil do que reinventar a roda.Aqui está um método de extensão LINQ genérico que não cria uma cópia extra da lista:
Para usá-lo:
Recentemente, criei este adicional que aceita um
ICompare<U>
, para que você possa personalizar a comparação. Isso veio a calhar quando eu precisava fazer uma ordenação Natural:fonte
OrderBy
faz tudo isso internamente.void
método de extensão nesse espírito: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))); } }
pode ser complementado por umSortByDescending
método. Os comentários do @ Servy também se aplicam ao meu código!Usando LINQ
fonte
fonte
Uma melhoria da versão de Roger.
O problema com GetDynamicSortProperty é que apenas obtemos os nomes das propriedades, mas o que acontece se no GridView usarmos NavigationProperties? ele enviará uma exceção, pois é nulo.
Exemplo:
"Employee.Company.Name;" falhará ... pois permite que apenas "Name" como parâmetro obtenha seu valor.
Aqui está uma versão aprimorada que nos permite classificar por Propriedades de navegação.
fonte
Você pode fazer algo mais genérico sobre a seleção de propriedades e ainda ser específico sobre o tipo de sua escolha, no seu caso 'Pedido':
escreva sua função como genérica:
e depois use-o assim:
Você pode ser ainda mais genérico e definir um tipo aberto para o que deseja solicitar:
e use da mesma maneira:
O que é uma maneira estúpida e desnecessária e complexa de executar um estilo LINQ 'OrderBy', mas pode fornecer uma pista de como ele pode ser implementado de maneira genérica
fonte
Deixe-me completar a resposta de @LukeH com algum código de exemplo, pois eu o testei e acredito que possa ser útil para alguns:
fonte
fonte
Faça uso do LiNQ
OrderBy
fonte
Baseado no comparador de GenericTypeTea :
podemos obter mais flexibilidade adicionando sinalizadores de classificação:
Nesse cenário, você deve instancia-lo como MyOrderingClass explicitamente (em vez de IComparer )
para definir suas propriedades de classificação:
fonte
Nenhuma das respostas acima foi genérica o suficiente para mim, então eu fiz esta:
Cuidado com conjuntos de dados massivos. É um código fácil, mas pode causar problemas se a coleção for enorme e o tipo de objeto da coleção tiver um grande número de campos. O tempo de execução é NxM, onde:
N = Nº de elementos na coleção
M = Nº de propriedades no objeto
fonte
Qualquer pessoa que trabalhe com tipos anuláveis
Value
deve usarCompareTo
.objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));
fonte
Do ponto de vista do desempenho, o melhor é usar uma lista classificada para que os dados sejam classificados conforme são adicionados ao resultado. Outras abordagens precisam de pelo menos uma iteração extra nos dados e a maioria cria uma cópia dos dados, para não apenas o desempenho, mas também o uso da memória. Pode não haver um problema com algumas centenas de elementos, mas estará com milhares, especialmente em serviços onde muitas solicitações simultâneas podem fazer a classificação ao mesmo tempo. Dê uma olhada no espaço para nome System.Collections.Generic e escolha uma classe com classificação em vez de Lista.
E evite implementações genéricas usando reflexão sempre que possível, isso também pode causar problemas de desempenho.
fonte
Suponha que você tenha o código a seguir; nesse código, temos uma classe Passenger com algumas propriedades nas quais queremos classificar com base.
Portanto, você pode implementar sua estrutura de classificação usando o delegado Composition.
fonte