web-dev-qa-db-fra.com

Comment trier un IEnumerable <string>

Comment puis-je trier un IEnumerable<string> par ordre alphabétique. Est-ce possible?

Edit: Comment pourrais-je écrire une solution sur place?

87
CatZilla

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

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.

9
James Curran
myEnumerable = myEnumerable.OrderBy(s => s);
8
Larsenal

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);
  }
}
2
Jon Hanna