c# generics sorting ilist

Clasificando un IList en C#



generics sorting (14)

Útil para la ordenación en cuadrícula, este método ordena la lista en función de los nombres de las propiedades. Como sigue el ejemplo.

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

Así que me encontré con un problema interesante hoy. Tenemos un servicio web de WCF que devuelve un IList. No fue realmente un gran problema hasta que quise ordenarlo.

Resulta que la interfaz IList no tiene un método de clasificación incorporado.

Terminé usando el método ArrayList.Adapter(list).Sort(new MyComparer()) para resolver el problema, pero me pareció un poco "ghetto".

Jugué con la escritura de un método de extensión, también con la herencia de IList y la implementación de mi propio método Sort (), así como el lanzamiento a una lista, pero ninguno de estos parecía excesivamente elegante.

Entonces mi pregunta es, ¿alguien tiene una solución elegante para clasificar un IList?


¿Es esta una solución válida?

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

El resultado fue: IList B A C

Lista A B C

IList nuevamente A B C


¿Qué hay de usar LINQ To Objects para ordenar por usted?

Digamos que tiene un IList<Car> , y el automóvil tenía una propiedad Engine , creo que podría ordenar de la siguiente manera:

from c in list orderby c.Engine select c;

Editar: necesitas ser rápido para obtener respuestas aquí. Como presenté una sintaxis ligeramente diferente a las otras respuestas, dejaré mi respuesta; sin embargo, las otras respuestas presentadas son igualmente válidas.


Aquí hay un ejemplo usando la tipificación más fuerte. Sin embargo, no estoy seguro si es necesariamente la mejor manera.

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 función Cast es solo una reimplementación del método de extensión que viene con 3.5 escrito como un método estático normal. Es bastante desagradable y verboso por desgracia.


Convierta su IList en List<T> o en alguna otra colección genérica y luego puede consultarla / ordenarla fácilmente utilizando el espacio de nombres System.Linq (proporcionará varios métodos de extensión)


En VS2008, cuando hago clic en la referencia del servicio y selecciono "Configurar referencia de servicio", hay una opción para elegir cómo el cliente deserializa las listas devueltas desde el servicio.

Notablemente, puedo elegir entre System.Array, System.Collections.ArrayList y System.Collections.Generic.List


Encontré este hilo mientras estaba buscando una solución al problema exacto descrito en la publicación original. Sin embargo, ninguna de las respuestas satisfizo mi situación por completo. La respuesta de Brody fue bastante cercana. Aquí está mi situación y solución que encontré.

Tengo dos ILists del mismo tipo devueltos por NHibernate y han surgido los dos IList en uno, de ahí la necesidad de ordenar.

Al igual que Brody, dije que implementé un ICompare en el objeto (ReportFormat) que es el tipo de mi IList:

public class FormatCcdeSorter:IComparer<ReportFormat> { public int Compare(ReportFormat x, ReportFormat y) { return x.FormatCode.CompareTo(y.FormatCode); } }

Luego convierto el IList fusionado a una matriz del mismo tipo:

ReportFormat[] myReports = new ReportFormat[reports.Count]; //reports is the merged IList

Luego ordena la matriz:

Array.Sort(myReports, new FormatCodeSorter());//sorting using custom comparer

Como la matriz unidimensional implementa la interfaz System.Collections.Generic.IList<T> , la matriz se puede usar como la IList original.


Encontré una buena publicación sobre esto y pensé que compartiría. Compruébalo AQUÍ

Básicamente.

Puede crear la siguiente clase y Clases 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); } }

Entonces, si tienes un IList, puedes ordenarlo así.

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

Pero revisa este sitio para obtener más información ... Échale un vistazo AQUÍ


Esta pregunta me inspiró a escribir una publicación de blog: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

Creo que, idealmente, .NET Framework incluiría un método de clasificación estático que acepta un IList <T>, pero lo mejor es crear su propio método de extensión. No es demasiado difícil crear un par de métodos que le permitirán ordenar un IList <T> como lo haría con una Lista <T>. Como beneficio adicional, puede sobrecargar el método de extensión LINQ OrderBy usando la misma técnica, de modo que ya sea que use List.Sort, IList.Sort o IEnumerable.OrderBy, puede usar la misma sintaxis.

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

Con estas extensiones, clasifique su IList como lo haría con una Lista:

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

Hay más información en la publicación: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/


La respuesta aceptada por @DavidMills es bastante buena, pero creo que se puede mejorar. Para empezar, no es necesario definir la clase ComparisonComparer<T> cuando el framework ya incluye un método estático Comparer<T>.Create(Comparison<T>) . Este método se puede usar para crear un IComparison sobre la marcha.

Además, arroja IList<T> a IList que tiene el potencial de ser peligroso. En la mayoría de los casos que he visto, List<T> que implementa IList se usa detrás de escena para implementar IList<T> , pero esto no está garantizado y puede llevar a código frágil.

Por último, el método List<T>.Sort() sobrecargado tiene 4 firmas y solo se implementan 2 de ellas.

  1. List<T>.Sort()
  2. List<T>.Sort(Comparison<T>)
  3. List<T>.Sort(IComparer<T>)
  4. List<T>.Sort(Int32, Int32, IComparer<T>)

La clase inferior implementa las 4 firmas List<T>.Sort() para la interfaz IList<T> :

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

Uso:

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

La idea aquí es aprovechar la funcionalidad de la List<T> subyacente List<T> para manejar la clasificación siempre que sea posible. De nuevo, la mayoría de IList<T> implementaciones IList<T> que he visto usan esto. En el caso en que la colección subyacente sea de un tipo diferente, retroceda a la creación de una nueva instancia de List<T> con elementos de la lista de entrada, utilícela para hacer la ordenación y luego copie los resultados nuevamente en la lista de entrada. Esto funcionará incluso si la lista de entrada no implementa la interfaz IList .


Puedes usar LINQ:

using System.Linq; IList<Foo> list = new List<Foo>(); IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar); IList<Foo> sortedList = sortedEnum.ToList();


Tendrás que hacer algo así, creo (convertirlo en un tipo más concreto).

Tal vez incluirlo en una lista de T en lugar de ArrayList, para que pueda obtener seguridad de tipo y más opciones sobre cómo implementar el comparador.


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


using System.Linq; var yourList = SomeDAO.GetRandomThings(); yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) );

Eso es bonito! Ghetto.