2010-09-02 8 views

Respuesta

114

La misma forma en que ordenar cualquier otra enumerables:

var result = myEnumerable.OrderBy(s => s); 

o

var result = from s in myEnumerable 
      orderby s 
      select s; 

o (ignorando caso)

var result = myEnumerable.OrderBy(s => s, 
            StringComparer.CurrentCultureIgnoreCase); 

Tenga en cuenta que, como es habitual en LINQ , esto crea un nuevo IEnumerable <T> que, cuando se enumera, devuelve los elementos de el IEnumerable original <T> en orden ordenado. No ordena el IEnumerable <T> en contexto.


un IEnumerable <T> es de sólo lectura, es decir, sólo se puede recuperar los elementos de ella, pero no puede modificar directamente. Si desea ordenar una colección de cadenas en el lugar, lo que necesita para ordenar la colección original que implementa IEnumerable <cadena>, o convertir un IEnumerable <cadena> en una colección puede ordenar primero:

List<string> myList = myEnumerable.ToList(); 
myList.Sort(); 

basado en su comentario:

_components = (from c in xml.Descendants("component") 
       let value = (string)c 
       orderby value 
       select value 
      ) 
       .Distinct() 
       .ToList(); 

o

_components = xml.Descendants("component") 
       .Select(c => (string)c) 
       .Distinct() 
       .OrderBy(v => v) 
       .ToList(); 

o (si desea agregar más adelante más elementos a la lista y mantenerla ordenada)

_components = xml.Descendants("component") 
       .Select(c => (string)c) 
       .Distinct() 
       .ToList(); 

_components.Add("foo"); 
_components.Sort(); 
+0

o myEnumerable.OrderByDescending (s => s). – Grozz

+0

+1, podría incluir ignorar el estuche. – user7116

+0

Entonces, _components = _components.OrderBy (s => s); ¿estaría bien? – CatZilla

8

Es imposible, pero no lo es.

Básicamente, cualquier método para ordenar va a copiar su IEnumerable en un List, ordenar la List y luego regresar a que la lista ordenada, que es un IEnumerable así como un IList.

Esto significa que pierde la propiedad "continuar infinitamente" de un IEnumerable, pero no puede ordenar uno así de todos modos.

+6

Derecho encendido. El objetivo de IEnumerable es presentarle un identificador de una serie que puede iterar, de principio a fin, al continuar solicitando el "siguiente" elemento. Esto significa que un IEnumerable se puede iterar parcialmente antes de que se conozcan todos los contenidos; no tiene que saber cuándo ha pasado por todos ellos hasta que lo haya hecho. La ordenación (como muchas otras cosas que Linq te permite) requiere el conocimiento de toda la serie como una lista ordenada; el artículo que aparecería primero en una serie ordenada puede ser el último devuelto por una serie, y usted no lo sabrá a menos que sepa cuáles son todos los artículos. – KeithS

8
myEnumerable = myEnumerable.OrderBy(s => s); 
2

No siempre podemos hacerlo en el lugar, pero detectar cuando es posible:

IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, IComparer<T> cmp) 
{ 
    List<T> listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src); 
    listToSort.Sort(cmp); 
    return listToSort; 
} 
IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, Comparison<T> cmp) 
{ 
    return SortInPlaceIfCan(src, new FuncComparer<T>(cmp)); 
} 
IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src) 
{ 
    return SortInPlaceIfCan(src, Comparer<T>.Default); 
} 

Este utiliza la siguiente estructura útil:

internal struct FuncComparer<T> : IComparer<T> 
{ 
    private readonly Comparison<T> _cmp; 
    public FuncComparer(Comparison<T> cmp) 
    { 
     _cmp = cmp; 
    } 
    public int Compare(T x, T y) 
    { 
     return _cmp(x, y); 
    } 
} 
+0

No estoy seguro de si lo recomendaría. Si tiene un IEnumerable pero no conoce el tipo real que implementa, probablemente no deba modificarlo. Por cierto, Array.FunctorComparer es interno. – dtb

+0

Al modificar lo que tenemos, tomé eso para estar implícito en la pregunta buscando en el lugar; que lo implica. Es una razón para tener "InPlaceInCan" en el nombre del método; los nombres de métodos pueden ser aún más directos sobre los riesgos que la mejor documentación;) Sí, Array.FunctorComparer es interno, pero es trivial. Lo puse porque es la mejor manera en que podría pensar en un ejemplo para "su comparador de funcionador que tiene en su conjunto de clases de ayuda". –

+0

@dtb en segundos pensamientos, cambiado para usar el mío (eché un vistazo a Array.FunctorComparer otra vez y prefiero el mío de todos modos!) –

Cuestiones relacionadas