J'ai une classe appelée Order
qui a des propriétés telles que OrderId
, OrderDate
, Quantity
, et Total
. J'ai une liste de cette Order
classe:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
Maintenant, je veux trier la liste en fonction d'une propriété de l' Order
objet, par exemple, je dois la trier par la date ou l'id de la commande.
Comment puis-je faire cela en C #?
Réponses:
La façon la plus simple à laquelle je peux penser est d'utiliser Linq:
la source
listWithObjects = listWithObjects.OrderByDescending(o => o.Status).ToList();
suffira pour une telle entreprise?Si vous devez trier la liste sur place, vous pouvez utiliser la
Sort
méthode en passant unComparison<T>
délégué:Si vous préférez créer une nouvelle séquence triée plutôt que de trier sur place, vous pouvez utiliser la
OrderBy
méthode de LINQ , comme mentionné dans les autres réponses.la source
x
ety
sur le côté droit de la flèche=>
.Nullable<>
(prenezDateTime?
l'exemple), vous pouvez utiliser.Sort((x, y) => Nullable.Compare(x.OrderDate, y.OrderDate))
ce qui traitera null comme précédant toutes les valeurs non nulles. C'est exactement la même chose que.Sort((x, y) => Comparer<DateTime?>.Default.Compare(x.OrderDate, y.OrderDate)
.Pour ce faire sans LINQ sur .Net2.0:
Si vous êtes sur .Net3.0, alors la réponse de LukeH est ce que vous recherchez.
Pour trier sur plusieurs propriétés, vous pouvez toujours le faire au sein d'un délégué. Par exemple:
Cela vous donnerait des dates ascendantes avec des ID de commande décroissants .
Cependant, je ne recommanderais pas de coller les délégués car cela signifiera beaucoup d'endroits sans réutilisation de code. Vous devez implémenter un
IComparer
et simplement le transmettre à votreSort
méthode. Voyez ici .Et puis, pour utiliser cette classe IComparer, instanciez-la simplement et passez-la à votre méthode Sort:
la source
IComparer
implémentations, nous donnant un comportement polymorphe.La manière la plus simple de commander une liste est d'utiliser
OrderBy
Si vous souhaitez commander par plusieurs colonnes, comme la requête SQL suivante.
Pour y parvenir, vous pouvez utiliser
ThenBy
comme suit.la source
Le faire sans Linq comme vous l'avez dit:
Ensuite, appelez simplement .sort () sur votre liste de commandes
la source
null
sur leas
casting. C'est tout l'intérêt deas
, car (ha, ha)(Order)obj
lève une exception en cas d'échec.if(orderToCompare == null) return 1;
.as
retournenull
si le casting échoue. Mais au moins, le test nul a raison.List<Order>
donc le type doit être garanti pour correspondre sur leas
2014 donc vous n'avez probablement pas écrit un bug, autant que d'éviter une déclaration de garde inutile :)List<Order>
; mais vous et moi avons tous deux rencontré le programmeur auto-encapsulé dont la présomption tacite est "j'écris ce code pour qu'il ne soit pas mal utilisé"Une solution orientée objet classique
Je dois d'abord faire une génuflexion sur le caractère génial de LINQ .... Maintenant que nous avons mis cela de côté
Une variation sur la réponse de JimmyHoffa. Avec les génériques, le
CompareTo
paramètre devient de type sécurisé.Cette triabilité par défaut est bien sûr réutilisable. Autrement dit, chaque client n'a pas à réécrire de manière redondante la logique de tri. L'échange du "1" et du "-1" (ou des opérateurs logiques, votre choix) inverse l'ordre de tri.
la source
this
objet est supérieur à null. Aux fins du tri, une référence d'objet nul "est inférieure à"this
objet. C'est juste la façon dont j'ai décidé de définir comment les valeurs nulles seront triées.// Tri totalement générique à utiliser avec une vue en grille
la source
data.OrderBy()
. Un peu plus facile que de réinventer la roue.Voici une méthode d'extension LINQ générique qui ne crée pas de copie supplémentaire de la liste:
Pour l'utiliser:
J'ai récemment construit celui-ci supplémentaire qui accepte un
ICompare<U>
, afin que vous puissiez personnaliser la comparaison. Cela m'a été utile lorsque j'ai dû faire un tri de chaîne naturelle:la source
OrderBy
fait tout cela en interne.void
méthode d'extension dans cet esprit: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))); } }
peut être complétée par uneSortByDescending
méthode. Les commentaires de @ Servy s'appliquent également à mon code!Utilisation de LINQ
la source
la source
Une amélioration de la version de Roger.
Le problème avec GetDynamicSortProperty est que seulement obtenir les noms de propriété, mais que se passe-t-il si dans le GridView nous utilisons NavigationProperties? il enverra une exception, car il trouve null.
Exemple:
"Employee.Company.Name;" se bloque ... car n'autorise que "Name" comme paramètre pour obtenir sa valeur.
Voici une version améliorée qui nous permet de trier par les propriétés de navigation.
la source
Vous pouvez faire quelque chose de plus générique sur la sélection des propriétés tout en étant précis sur le type à partir duquel vous sélectionnez, dans votre cas «Ordre»:
écrivez votre fonction comme une fonction générique:
puis utilisez-le comme ceci:
Vous pouvez être encore plus générique et définir un type ouvert pour ce que vous souhaitez commander:
et utilisez-le de la même manière:
Ce qui est une manière complexe et stupide et inutile de faire un `` OrderBy '' de style LINQ, mais cela peut vous donner un indice sur la façon dont il peut être implémenté de manière générique
la source
Veuillez me laisser compléter la réponse par @LukeH avec un exemple de code, car je l'ai testé, je pense que cela peut être utile pour certains:
la source
la source
Utilisez LiNQ
OrderBy
la source
Basé sur Comparer de GenericTypeTea:
nous pouvons obtenir plus de flexibilité en ajoutant des drapeaux de tri:
Dans ce scénario, vous devez l'instancier explicitement en tant que MyOrderingClass (plutôt qu'IComparer )
afin de définir ses propriétés de tri:
la source
Aucune des réponses ci-dessus n'était assez générique pour moi, alors j'ai fait celle-ci:
Attention toutefois aux ensembles de données massifs. C'est un code facile mais pourrait vous causer des ennuis si la collection est énorme et que le type d'objet de la collection a un grand nombre de champs. Le temps d'exécution est NxM où:
N = nombre d'éléments dans la collection
M = nombre de propriétés dans l'objet
la source
Toute personne travaillant avec des types nullables
Value
doit utiliserCompareTo
.objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));
la source
Du point de vue des performances, le mieux est d'utiliser une liste triée afin que les données soient triées au fur et à mesure qu'elles sont ajoutées au résultat. D'autres approches nécessitent au moins une itération supplémentaire sur les données et la plupart créent une copie des données afin que non seulement les performances, mais l'utilisation de la mémoire soient également affectées. Peut ne pas être un problème avec quelques centaines d'éléments mais le sera avec des milliers, en particulier dans les services où de nombreuses demandes simultanées peuvent effectuer un tri en même temps. Jetez un œil à l'espace de noms System.Collections.Generic et choisissez une classe avec tri au lieu de List.
Et évitez les implémentations génériques utilisant la réflexion lorsque cela est possible, cela peut également entraîner des problèmes de performances.
la source
Supposons que vous ayez le code suivant, dans ce code, nous avons une classe Passenger avec quelques propriétés sur lesquelles nous voulons trier.
Vous pouvez donc implémenter votre structure de tri en utilisant Délégué de composition.
la source