Comment puis-je trier un IEnumerable<string>
fichier par ordre alphabétique. Est-ce possible?
Edit: Comment pourrais-je écrire une solution sur place?
Réponses:
De la même manière que 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 (sans tenir compte de la casse)
var result = myEnumerable.OrderBy(s => s,
StringComparer.CurrentCultureIgnoreCase);
Notez que, comme d'habitude avec LINQ, cela crée un nouveau IEnumerable <T> qui, lorsqu'il est énuméré, retourne les éléments du IEnumerable <T> d'origine dans l'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 en récupérer que les éléments, mais ne pouvez pas le modifier directement. Si vous souhaitez trier une collection de chaînes sur place, vous devez d'abord trier la collection d'origine qui implémente IEnumerable <string>, ou transformer une IEnumerable <string> en une collection triable en premier:
List<string> myList = myEnumerable.ToList();
myList.Sort();
Sur la base de 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 d'autres éléments à la liste et la conserver triée)
_components = xml.Descendants("component")
.Select(c => (string)c)
.Distinct()
.ToList();
_components.Add("foo");
_components.Sort();
OrderBy
revient IOrderedEnumerable<T>
. IOrderedEnumerable<T>
dérive de IEnumerable<T>
donc il peut être utilisé comme IEnumerable<T>
, mais il étend le type, permettant par exemple, l'utilisation de ThenBy
.
C'est impossible, mais ce n'est pas le cas.
Fondamentalement, toute méthode de tri va copier votre IEnumerable
dans un List
, trier le List
puis vous retourner la liste triée, qui est IEnumerable
aussi bien un fichier IList
.
Cela signifie que vous perdez la propriété "continue infiniment" d'un IEnumerable
, mais vous ne pouvez pas en trier une comme ça de toute façon.
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);
}
Cela 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);
}
}
listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);
? Que diriez-vous de l'avoir commelistToSort = (src as List<T>); if (null == listToSort) listToSort = new List<T>(src);