2010-09-02 11 views

risposta

114

Lo stesso modo che ci ordinare qualsiasi altro enumerabile:

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

o

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

o (caso ignorando)

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

Nota che, come al solito con LINQ , questo crea un nuovo IEnumerable <T> che, quando enumerato, restituisce gli elementi di l'originale IEnumerable <T> in ordine ordinato. Non ordina l'IEnumerable <T> sul posto.


un IEnumerable <T> è di sola lettura, cioè, è possibile recuperare solo gli elementi da esso, ma non può modificare direttamente. Se si desidera ordinare una collezione di stringhe in-luogo, è necessario risolvere la collezione originale che implementa IEnumerable <stringa>, o girare un < stringa IEnumerable > in una collezione ordinabile prima:

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

sulla base della sua commento:

_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 (se si desidera aggiungere in seguito altri elementi alla lista e tenerlo allineati)

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

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

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

+0

+1, potrebbe includere ignorare il caso. – user7116

+0

Quindi, _components = _components.OrderBy (s => s); andrebbe bene? – CatZilla

8

E 'impossibile, ma non lo è.

In sostanza, qualsiasi metodo di ordinamento sta per copiare il IEnumerable in un List, ordinare la List e poi tornare a voi la lista ordinata, che è un IEnumerable così come un IList.

Ciò significa che si perde la proprietà "continua all'infinito" di uno IEnumerable, ma in questo caso non è possibile selezionarne uno simile.

+6

Esatto. Lo scopo di IEnumerable è quello di presentarti un handle per una serie che puoi iterare, dall'inizio alla fine, continuando a chiedere l'elemento "next". Ciò significa che un oggetto IEnumerable può essere parzialmente iterato prima che tutti i contenuti siano conosciuti; non devi sapere quando li hai attraversati tutti fino a quando non l'hai fatto. L'ordinamento (come molte cose che Linq consente di fare) richiede la conoscenza dell'intera serie come una lista ordinata; l'elemento che appare per primo in una serie ordinata potrebbe essere l'ultimo restituito da una serie e non lo saprai a meno che tu non sappia cosa sono tutti gli articoli. – KeithS

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

Non possiamo sempre farlo sul posto, ma noi di rilevare quando è possibile:

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

Questo utilizza la seguente struct a portata di mano:

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

Non sono sicuro se lo consiglierei. Se possiedi un oggetto IEnumerable ma non conosci il tipo effettivo che implementa, probabilmente non dovresti modificarlo. Btw, Array.FunctorComparer è interno. – dtb

+0

Nel modificare ciò che abbiamo, ho preso ciò che è implicito nella domanda in cerca di posto; che lo sottintende. È un motivo per avere "InPlaceInCan" nel nome del metodo; i nomi dei metodi possono essere ancora più precoci sui rischi rispetto alla migliore documentazione;) Sì, Array.FunctorComparer è interno, ma è banale. L'ho inserito perché è il modo migliore in cui potrei pensare in un esempio per "il tuo comparatore di funzioni che hai nel tuo go-to set di classi di supporto". –

+0

@dtb su ripensamenti, cambiato per usare il mio (dai un'occhiata a Array.FunctorComparer di nuovo e preferisco il mio comunque!) –

Problemi correlati