Jak mogę posortować IEnumerable<string>
alfabetycznie. czy to możliwe?
Edycja: Jak napisać rozwiązanie lokalne?
Odpowiedzi:
W ten sam sposób, w jaki posortowałbyś inne wyliczalne:
var result = myEnumerable.OrderBy(s => s);
lub
var result = from s in myEnumerable
orderby s
select s;
lub (ignorując wielkość liter)
var result = myEnumerable.OrderBy(s => s,
StringComparer.CurrentCultureIgnoreCase);
Należy zauważyć, że, jak zwykle w przypadku LINQ, tworzy to nowy IEnumerable <T>, który po wyliczeniu zwraca elementy oryginalnego IEnumerable <T> w kolejności posortowanej. Nie sortuje IEnumerable <T> w miejscu.
IEnumerable <T> jest tylko do odczytu, co oznacza, że można pobrać z niego tylko elementy, ale nie można go bezpośrednio modyfikować. Jeśli chcesz posortować kolekcję ciągów w miejscu, musisz najpierw posortować oryginalną kolekcję, która implementuje IEnumerable <string>, lub zamienić IEnumerable <string> w kolekcję, którą można sortować:
List<string> myList = myEnumerable.ToList();
myList.Sort();
Na podstawie Twojego komentarza:
_components = (from c in xml.Descendants("component")
let value = (string)c
orderby value
select value
)
.Distinct()
.ToList();
lub
_components = xml.Descendants("component")
.Select(c => (string)c)
.Distinct()
.OrderBy(v => v)
.ToList();
lub (jeśli chcesz później dodać więcej pozycji do listy i zachować ją posortowaną)
_components = xml.Descendants("component")
.Select(c => (string)c)
.Distinct()
.ToList();
_components.Add("foo");
_components.Sort();
OrderBy
zwraca IOrderedEnumerable<T>
. IOrderedEnumerable<T>
wywodzi się z, IEnumerable<T>
więc może być używany jak IEnumerable<T>
, ale rozszerza typ, pozwalając na przykład na użycie ThenBy
.
To niemożliwe, ale tak nie jest.
Zasadniczo każda metoda sortowania skopiuje twoją IEnumerable
do a List
, posortuje, List
a następnie zwróci do ciebie posortowaną listę, która jest IEnumerable
zarówno plikiem IList
.
Oznacza to, że tracisz właściwość „kontynuuj w nieskończoność” IEnumerable
, ale i tak nie możesz tak posortować.
Nie zawsze możemy to zrobić na miejscu, ale wykrywamy, kiedy jest to możliwe:
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);
}
Używa to następującej przydatnej struktury:
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);
? A co powiesz na tolistToSort = (src as List<T>); if (null == listToSort) listToSort = new List<T>(src);