Je suis donc tombé sur un problème intéressant aujourd'hui. Nous avons un service Web WCF qui renvoie un IList. Pas vraiment grand-chose jusqu'à ce que je veuille régler ça.
Il s'avère que l'interface IList n'a pas de méthode de tri intégrée.
J'ai fini par utiliser la ArrayList.Adapter(list).Sort(new MyComparer())
méthode pour résoudre le problème, mais cela me semblait un peu «ghetto».
J'ai joué avec l'écriture d'une méthode d'extension, également avec l'héritage de IList et l'implémentation de ma propre méthode Sort () ainsi que le cast dans une liste, mais aucun de ceux-ci ne semblait trop élégant.
Ma question est donc la suivante: est-ce que quelqu'un a une solution élégante pour trier un IList
Réponses:
Que diriez-vous d'utiliser LINQ To Objects pour trier pour vous?
Disons que vous avez un
IList<Car>
, et que la voiture a uneEngine
propriété, je pense que vous pouvez trier comme suit:from c in list orderby c.Engine select c;
Edit: Vous devez être rapide pour obtenir des réponses ici. Comme j'ai présenté une syntaxe légèrement différente des autres réponses, je laisserai ma réponse - cependant, les autres réponses présentées sont également valables.
la source
Vous pouvez utiliser LINQ:
using System.Linq; IList<Foo> list = new List<Foo>(); IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar); IList<Foo> sortedList = sortedEnum.ToList();
la source
Cette question m'a inspiré pour écrire un article de blog: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
Je pense que, idéalement, le .NET Framework inclurait une méthode de tri statique qui accepte un IList <T>, mais la meilleure chose à faire est de créer votre propre méthode d'extension. Il n'est pas trop difficile de créer quelques méthodes qui vous permettront de trier un IList <T> comme vous le feriez pour un List <T>. En prime, vous pouvez surcharger la méthode d'extension LINQ OrderBy en utilisant la même technique, de sorte que que vous utilisiez List.Sort, IList.Sort ou IEnumerable.OrderBy, vous puissiez utiliser exactement la même syntaxe.
public static class SortExtensions { // Sorts an IList<T> in place. public static void Sort<T>(this IList<T> list, Comparison<T> comparison) { ArrayList.Adapter((IList)list).Sort(new ComparisonComparer<T>(comparison)); } // Sorts in IList<T> in place, when T is IComparable<T> public static void Sort<T>(this IList<T> list) where T: IComparable<T> { Comparison<T> comparison = (l, r) => l.CompareTo(r); Sort(list, comparison); } // Convenience method on IEnumerable<T> to allow passing of a // Comparison<T> delegate to the OrderBy method. public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, Comparison<T> comparison) { return list.OrderBy(t => t, new ComparisonComparer<T>(comparison)); } } // Wraps a generic Comparison<T> delegate in an IComparer to make it easy // to use a lambda expression for methods that take an IComparer or IComparer<T> public class ComparisonComparer<T> : IComparer<T>, IComparer { private readonly Comparison<T> _comparison; public ComparisonComparer(Comparison<T> comparison) { _comparison = comparison; } public int Compare(T x, T y) { return _comparison(x, y); } public int Compare(object o1, object o2) { return _comparison((T)o1, (T)o2); } }
Avec ces extensions, triez votre IList comme vous le feriez pour une liste:
IList<string> iList = new [] { "Carlton", "Alison", "Bob", "Eric", "David" }; // Use the custom extensions: // Sort in-place, by string length iList.Sort((s1, s2) => s1.Length.CompareTo(s2.Length)); // Or use OrderBy() IEnumerable<string> ordered = iList.OrderBy((s1, s2) => s1.Length.CompareTo(s2.Length));
Il y a plus d'informations dans le post: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/
la source
ISortableList<T>
interface (avec des méthodes pour trier une partie de la liste en utilisant un comparateur particulier), de l'List<T>
implémenter et d'avoir une méthode statique qui pourrait en trierIList<T>
en vérifiant si elle est implémentéeISortableList<T>
et, sinon, en le copiant dans un tableau, en le triant, en effaçantIList<T>
et en ajoutant à nouveau les éléments.IList<T> list
peut être transtypé vers l'IList
interface non générique . Si vous codez votre propre classe implémentant l'IList<T>
interface, assurez-vous que vous implémentez également l'IList
interface non générique , sinon le code échouera avec une exception de conversion de classe.ISortableList<T>
offrir ce qui n'est pas déjà faitIList<T>
? Ou, demandé différemment, pourquoi ne pourrait-on pasIList<T>
trier un sur place sans rajouter les éléments par votre méthode statique imaginée?IList<T>
interface pour accéder à chaque élément. La différence de vitesse est suffisamment grande pour que dans de nombreux cas, il puisse être plus rapide de copier une liste dans un tableau, de trier le tableau et de recopier la liste, que d'essayer de mettre en place une routine de tri pour traiter la liste.ComparisonComparer
classe n'est pas nécessaire. Vous pouvez utiliser la méthode statique standard à laComparer<T>.Create(comparison)
place.Vous allez devoir faire quelque chose comme ça je pense (le convertir en un type plus concret).
Peut-être le prendre dans une liste de T plutôt que dans ArrayList, de sorte que vous obteniez la sécurité de type et plus d'options pour la façon dont vous implémentez le comparateur.
la source
La réponse acceptée par @DavidMills est assez bonne, mais je pense qu'elle peut être améliorée. D'une part, il n'est pas nécessaire de définir la
ComparisonComparer<T>
classe lorsque le framework inclut déjà une méthode statiqueComparer<T>.Create(Comparison<T>)
. Cette méthode peut être utilisée pour créer un fichierIComparison
à la volée.En outre, il jette
IList<T>
àIList
qui a le potentiel d'être dangereux. Dans la plupart des cas que j'ai vus,List<T>
quels outilsIList
sont utilisés dans les coulisses pour implémenterIList<T>
, mais ce n'est pas garanti et peut conduire à un code fragile.Enfin, la
List<T>.Sort()
méthode surchargée a 4 signatures et seulement 2 d'entre elles sont implémentées.List<T>.Sort()
List<T>.Sort(Comparison<T>)
List<T>.Sort(IComparer<T>)
List<T>.Sort(Int32, Int32, IComparer<T>)
La classe ci-dessous implémente les 4
List<T>.Sort()
signatures pour l'IList<T>
interface:using System; using System.Collections.Generic; public static class IListExtensions { public static void Sort<T>(this IList<T> list) { if (list is List<T>) { ((List<T>)list).Sort(); } else { List<T> copy = new List<T>(list); copy.Sort(); Copy(copy, 0, list, 0, list.Count); } } public static void Sort<T>(this IList<T> list, Comparison<T> comparison) { if (list is List<T>) { ((List<T>)list).Sort(comparison); } else { List<T> copy = new List<T>(list); copy.Sort(comparison); Copy(copy, 0, list, 0, list.Count); } } public static void Sort<T>(this IList<T> list, IComparer<T> comparer) { if (list is List<T>) { ((List<T>)list).Sort(comparer); } else { List<T> copy = new List<T>(list); copy.Sort(comparer); Copy(copy, 0, list, 0, list.Count); } } public static void Sort<T>(this IList<T> list, int index, int count, IComparer<T> comparer) { if (list is List<T>) { ((List<T>)list).Sort(index, count, comparer); } else { List<T> range = new List<T>(count); for (int i = 0; i < count; i++) { range.Add(list[index + i]); } range.Sort(comparer); Copy(range, 0, list, index, count); } } private static void Copy<T>(IList<T> sourceList, int sourceIndex, IList<T> destinationList, int destinationIndex, int count) { for (int i = 0; i < count; i++) { destinationList[destinationIndex + i] = sourceList[sourceIndex + i]; } } }
Usage:
class Foo { public int Bar; public Foo(int bar) { this.Bar = bar; } } void TestSort() { IList<int> ints = new List<int>() { 1, 4, 5, 3, 2 }; IList<Foo> foos = new List<Foo>() { new Foo(1), new Foo(4), new Foo(5), new Foo(3), new Foo(2), }; ints.Sort(); foos.Sort((x, y) => Comparer<int>.Default.Compare(x.Bar, y.Bar)); }
L'idée ici est de tirer parti de la fonctionnalité du sous-jacent
List<T>
pour gérer le tri dans la mesure du possible. Encore une fois, la plupart desIList<T>
implémentations que j'ai vues l'utilisent. Dans le cas où la collection sous-jacente est d'un type différent, revenez à la création d'une nouvelle instance deList<T>
avec des éléments de la liste d'entrée, utilisez-la pour effectuer le tri, puis copiez les résultats dans la liste d'entrée. Cela fonctionnera même si la liste d'entrée n'implémente pas l'IList
interface.la source
try this **USE ORDER BY** : public class Employee { public string Id { get; set; } public string Name { get; set; } } private static IList<Employee> GetItems() { List<Employee> lst = new List<Employee>(); lst.Add(new Employee { Id = "1", Name = "Emp1" }); lst.Add(new Employee { Id = "2", Name = "Emp2" }); lst.Add(new Employee { Id = "7", Name = "Emp7" }); lst.Add(new Employee { Id = "4", Name = "Emp4" }); lst.Add(new Employee { Id = "5", Name = "Emp5" }); lst.Add(new Employee { Id = "6", Name = "Emp6" }); lst.Add(new Employee { Id = "3", Name = "Emp3" }); return lst; } **var lst = GetItems().AsEnumerable(); var orderedLst = lst.OrderBy(t => t.Id).ToList(); orderedLst.ForEach(emp => Console.WriteLine("Id - {0} Name -{1}", emp.Id, emp.Name));**
la source
J'ai trouvé ce fil pendant que je cherchais une solution au problème exact décrit dans le message original. Aucune des réponses ne répondait entièrement à ma situation, cependant. La réponse de Brody était assez proche. Voici ma situation et la solution que j'y ai trouvée.
J'ai deux ILists du même type retournés par NHibernate et j'ai émergé les deux IList en un seul, d'où la nécessité de les trier.
Comme Brody l'a dit, j'ai implémenté un ICompare sur l'objet (ReportFormat) qui est le type de mon IList:
public class FormatCcdeSorter:IComparer<ReportFormat> { public int Compare(ReportFormat x, ReportFormat y) { return x.FormatCode.CompareTo(y.FormatCode); } }
Je convertis ensuite l'IList fusionné en un tableau du même type:
ReportFormat[] myReports = new ReportFormat[reports.Count]; //reports is the merged IList
Puis triez le tableau:
Array.Sort(myReports, new FormatCodeSorter());//sorting using custom comparer
Puisque le tableau unidimensionnel implémente l'interface
System.Collections.Generic.IList<T>
, le tableau peut être utilisé comme l'IList d'origine.la source
Utile pour le tri par grille, cette méthode trie la liste en fonction des noms de propriété. Comme suivez l'exemple.
List<MeuTeste> temp = new List<MeuTeste>(); temp.Add(new MeuTeste(2, "ramster", DateTime.Now)); temp.Add(new MeuTeste(1, "ball", DateTime.Now)); temp.Add(new MeuTeste(8, "gimm", DateTime.Now)); temp.Add(new MeuTeste(3, "dies", DateTime.Now)); temp.Add(new MeuTeste(9, "random", DateTime.Now)); temp.Add(new MeuTeste(5, "call", DateTime.Now)); temp.Add(new MeuTeste(6, "simple", DateTime.Now)); temp.Add(new MeuTeste(7, "silver", DateTime.Now)); temp.Add(new MeuTeste(4, "inn", DateTime.Now)); SortList(ref temp, SortDirection.Ascending, "MyProperty"); private void SortList<T>( ref List<T> lista , SortDirection sort , string propertyToOrder) { if (!string.IsNullOrEmpty(propertyToOrder) && lista != null && lista.Count > 0) { Type t = lista[0].GetType(); if (sort == SortDirection.Ascending) { lista = lista.OrderBy( a => t.InvokeMember( propertyToOrder , System.Reflection.BindingFlags.GetProperty , null , a , null ) ).ToList(); } else { lista = lista.OrderByDescending( a => t.InvokeMember( propertyToOrder , System.Reflection.BindingFlags.GetProperty , null , a , null ) ).ToList(); } } }
la source
Voici un exemple utilisant le typage plus fort. Je ne sais pas si c'est forcément le meilleur moyen.
static void Main(string[] args) { IList list = new List<int>() { 1, 3, 2, 5, 4, 6, 9, 8, 7 }; List<int> stronglyTypedList = new List<int>(Cast<int>(list)); stronglyTypedList.Sort(); } private static IEnumerable<T> Cast<T>(IEnumerable list) { foreach (T item in list) { yield return item; } }
La fonction Cast est juste une réimplémentation de la méthode d'extension fournie avec 3.5 écrite comme une méthode statique normale. C'est assez laid et bavard malheureusement.
la source
Dans VS2008, lorsque je clique sur la référence de service et que je sélectionne "Configurer la référence de service", il y a une option pour choisir comment le client désérialise les listes renvoyées par le service.
Notamment, je peux choisir entre System.Array, System.Collections.ArrayList et System.Collections.Generic.List
la source
using System.Linq; var yourList = SomeDAO.GetRandomThings(); yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) );
C'est joli! Ghetto.
la source
J'ai trouvé un bon article à ce sujet et j'ai pensé partager. Vérifiez le ici
Fondamentalement.
Vous pouvez créer la classe suivante et les classes IComparer
public class Widget { public string Name = string.Empty; public int Size = 0; public Widget(string name, int size) { this.Name = name; this.Size = size; } } public class WidgetNameSorter : IComparer<Widget> { public int Compare(Widget x, Widget y) { return x.Name.CompareTo(y.Name); } } public class WidgetSizeSorter : IComparer<Widget> { public int Compare(Widget x, Widget y) { return x.Size.CompareTo(y.Size); } }
Ensuite, si vous avez un IList, vous pouvez le trier comme ceci.
List<Widget> widgets = new List<Widget>(); widgets.Add(new Widget("Zeta", 6)); widgets.Add(new Widget("Beta", 3)); widgets.Add(new Widget("Alpha", 9)); widgets.Sort(new WidgetNameSorter()); widgets.Sort(new WidgetSizeSorter());
Mais consultez ce site pour plus d'informations ... Consultez-le ICI
la source
Est-ce une solution valable?
IList<string> ilist = new List<string>(); ilist.Add("B"); ilist.Add("A"); ilist.Add("C"); Console.WriteLine("IList"); foreach (string val in ilist) Console.WriteLine(val); Console.WriteLine(); List<string> list = (List<string>)ilist; list.Sort(); Console.WriteLine("List"); foreach (string val in list) Console.WriteLine(val); Console.WriteLine(); list = null; Console.WriteLine("IList again"); foreach (string val in ilist) Console.WriteLine(val); Console.WriteLine();
Le résultat était: IList B A C
Liste A B C
IList à nouveau A B C
la source
Cela semble BEAUCOUP PLUS SIMPLE si vous me demandez. Cela fonctionne parfaitement pour moi.
Vous pouvez utiliser Cast () pour le changer en IList puis utiliser OrderBy ():
var ordered = theIList.Cast<T>().OrderBy(e => e);
WHERE T est le type par exemple. Model.Employee ou Plugin.ContactService.Shared.Contact
Ensuite, vous pouvez utiliser une boucle for et son DONE.
ObservableCollection<Plugin.ContactService.Shared.Contact> ContactItems= new ObservableCollection<Contact>(); foreach (var item in ordered) { ContactItems.Add(item); }
la source
Convertissez votre
IList
dansList<T>
ou d' une autre collection générique et vous pouvez facilement requête / trier à l'aide d'System.Linq
espace de noms (il fournira tas de méthodes d'extension)la source
IList<T>
implémenteIEnumerable<T>
et n'a donc pas besoin d'être converti pour utiliser les opérations Linq.