Как отсортировать IEnumerable <string>

Как сортировать IEnumerable<string> в алфавитном порядке. Возможно ли это?

Изменить: как мне написать решение на месте?

Ответ 1

Точно так же вы можете отсортировать любые другие перечисляемые файлы:

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

или

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

или (игнорируя случай)

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

Обратите внимание, что, как обычно в LINQ, это создает новый IEnumerable <T> который при перечислении возвращает элементы исходного IEnumerable <T> в отсортированном порядке. Он не сортирует IEnumerable <T> на месте.


IEnumerable <T> доступен только для чтения, т.е. вы можете извлекать из него только элементы, но не можете изменять его напрямую. Если вы хотите отсортировать коллекцию строк на месте, вам необходимо отсортировать исходную коллекцию, которая реализует IEnumerable <string> , или включить IEnumerable <string> сначала в сортируемую коллекцию:

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

На основе вашего комментария:

_components = (from c in xml.Descendants("component")
               let value = (string)c
               orderby value
               select value
              )
              .Distinct()
              .ToList();

или

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

или (если вы хотите позже добавить в список больше элементов и сохранить их сортировку)

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

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

Ответ 2

Это невозможно, но это не так.

В принципе, любой метод сортировки скопирует ваш IEnumerable в List, сортирует List, а затем возвращает вам отсортированный список, который является IEnumerable, а также IList.

Это означает, что вы потеряете свойство "продолжать бесконечно" IEnumerable, но тогда вы все равно не могли бы сортировать.

Ответ 3

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

Ответ 4

Мы не всегда можем делать это на месте, но обнаруживаем, когда это возможно:

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

Здесь используется следующая удобная структура:

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