Comment puis-je trier un IEnumerable<string>
par ordre alphabétique. Est-ce possible?
Edit: Comment pourrais-je écrire une solution sur place?
De la même manière, vous trieriez n'importe quel autre énumérable:
var result = myEnumerable.OrderBy(s => s);
ou
var result = from s in myEnumerable
orderby s
select s;
ou (en ignorant le cas)
var result = myEnumerable.OrderBy(s => s,
StringComparer.CurrentCultureIgnoreCase);
Notez que, comme d'habitude avec LINQ, ceci crée un nouveau IEnumerable <T> qui, lorsqu'il est énuméré, renvoie les éléments du IEnumerable <T> d'origine dans un ordre trié. Il ne trie pas le IEnumerable <T> sur place.
Un IEnumerable <T> est en lecture seule, c’est-à-dire que vous ne pouvez récupérer que les éléments, mais que vous ne pouvez pas le modifier directement. Si vous souhaitez trier une collection de chaînes sur place, vous devez trier la collection d'origine qui implémente IEnumerable <string> ou transformer une chaîne IEnumerable <string> en une collection pouvant être triée:
List<string> myList = myEnumerable.ToList();
myList.Sort();
Basé sur votre commentaire:
_components = (from c in xml.Descendants("component")
let value = (string)c
orderby value
select value
)
.Distinct()
.ToList();
ou
_components = xml.Descendants("component")
.Select(c => (string)c)
.Distinct()
.OrderBy(v => v)
.ToList();
ou (si vous souhaitez ajouter ultérieurement des éléments à la liste et les conserver triés)
_components = xml.Descendants("component")
.Select(c => (string)c)
.Distinct()
.ToList();
_components.Add("foo");
_components.Sort();
C'est impossible, mais ça ne l'est pas.
En gros, toute méthode de tri va copier votre IEnumerable
dans un List
, trier le List
puis vous retourner la liste triée, qui est un IEnumerable
ainsi qu'un IList
.
Cela signifie que vous perdez la propriété "continue infiniment" d'un IEnumerable
, mais vous ne pourriez pas en trier un comme ça de toute façon.
myEnumerable = myEnumerable.OrderBy(s => s);
Nous ne pouvons pas toujours le faire sur place, mais nous détectons quand c'est possible:
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);
}
Ceci utilise la structure pratique suivante:
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);
}
}