Как отсортировать IEnumerable <string> - PullRequest
86 голосов
/ 02 сентября 2010

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

Редактировать: Как бы я написал решение на месте?

Ответы [ 4 ]

139 голосов
/ 02 сентября 2010

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

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 , который при перечислении возвращает элементы исходного IEnumerable в отсортированном порядке. Он не сортирует IEnumerable на месте.


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

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();
9 голосов
/ 02 сентября 2010

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

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

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

8 голосов
/ 03 сентября 2010
myEnumerable = myEnumerable.OrderBy(s => s);
2 голосов
/ 03 сентября 2010

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

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