Как отсортировать по IEnumerable<string>
алфавиту. Это возможно?
Изменить: как мне написать решение на месте?
Ответы:
Так же, как и любое другое перечислимое:
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();
OrderBy
возвращается IOrderedEnumerable<T>
. IOrderedEnumerable<T>
является производным от, IEnumerable<T>
поэтому его можно использовать как подобный IEnumerable<T>
, но он расширяет тип, позволяя, например, использовать ThenBy
.
Это невозможно, но это не так.
По сути, любой метод сортировки скопирует ваш IEnumerable
в List
, отсортирует, List
а затем вернет вам отсортированный список, который является IEnumerable
как файлом IList
.
Это означает, что вы теряете свойство «продолжать бесконечно» IEnumerable
, но вы все равно не сможете отсортировать его таким образом.
Мы не всегда можем сделать это на месте, но мы обнаруживаем, когда это возможно:
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);
}
}
listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);
? Как насчет того, чтобы это было нравитсяlistToSort = (src as List<T>); if (null == listToSort) listToSort = new List<T>(src);