ti-enxame.com

Como classificar um IEnumerable <string>

Como posso classificar um IEnumerable<string> em ordem alfabética. Isso é possível?

Edit: Como eu escreveria uma solução no local?

87
CatZilla

Da mesma maneira que você classificaria qualquer outro enumerável:

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

ou

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

ou (ignorando maiúsculas e minúsculas)

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

Observe que, como é habitual no LINQ, isso cria um novo IEnumerable <T> que, quando enumerado, retorna os elementos do IEnumerable original <T> na ordem de classificação. Ele não classifica o IEnumerable <T> no local.


Um IEnumerable <T> é somente leitura, ou seja, você só pode recuperar os elementos, mas não pode modificá-lo diretamente. Se você deseja classificar uma coleção de seqüências de caracteres no local, é necessário classificar a coleção original que implementa IEnumerable <string> ou transformar um IEnumerable <string> em uma coleção classificável primeiro:

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

Com base no seu comentário:

_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 (se desejar adicionar mais itens à lista e mantê-la classificada)

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

_components.Add("foo");
_components.Sort();
140
dtb

É impossível, mas não é.

Basicamente, qualquer método de classificação copiará seu IEnumerable para um List, classifique o List e retornará a você a lista classificada, que é um IEnumerable e IList.

Isso significa que você perde a propriedade "continue infinitamente" de um IEnumerable, mas não pode classificar uma assim.

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

Nem sempre podemos fazer isso no local, mas detectamos quando é possível:

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

Isso usa a seguinte estrutura prática:

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