IEnumerable <string> nasıl sıralanır


100

IEnumerable<string>Alfabetik olarak nasıl sıralayabilirim . Mümkün mü?

Düzenleme: Yerinde bir çözümü nasıl yazarım?

Yanıtlar:


158

Diğer numaralandırılabilirleri sıraladığınız gibi:

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

veya

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

veya (büyük / küçük harfe bakılmaksızın)

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

LINQ ile her zamanki gibi, bu, numaralandırıldığında, orijinal IEnumerable <T> öğelerini sıralı sırada döndüren yeni bir IEnumerable <T> oluşturur. Yerinde IEnumerable <T> sıralamaz.


Bir IEnumerable <T> salt okunurdur, yani öğeleri yalnızca ondan alabilir, ancak doğrudan değiştiremezsiniz. Yerinde dizelerin bir koleksiyonunu sıralamak istiyorsanız, önce IEnumerable <string> uygulayan orijinal koleksiyonu sıralamanız veya bir IEnumerable <string> dizesini sıralanabilir bir koleksiyona dönüştürmeniz gerekir:

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

Yorumunuza göre:

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

veya

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

veya (daha sonra listeye daha fazla öğe eklemek ve sıralı tutmak isterseniz)

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

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

veya myEnumerable.OrderByDescending (s => s).
Grozz

Yani, _ bileşen = _ bileşen.OrderBy (s => s); iyi olur
CatZilla

@CatZilla: Bu işe yarayabilir, ancak gerçek sorununuzu çözmenin en iyi yolu olmayabilir. _Bileşen nedir, nereden alıyorsunuz, nasıl kullanıyorsunuz?
dtb

1
@dtb: Oh, _ bileşenleri tam olarak şu şekilde bir XML dosyasından doldurulur: _components = (xml.Descendants ("component") içindeki c'den c.Value.ToString ()). Distinct (). ToList (); Ve bunu düzeltmem gerekiyor.
CatZilla

2
OrderBydöner IOrderedEnumerable<T>. IOrderedEnumerable<T>türetildiği IEnumerable<T>gibi kullanılabilir IEnumerable<T>, ancak türü genişletir, örneğin kullanımına izin verir ThenBy.
Maciej Hehl

12

İmkansız ama değil.

Temel olarak, herhangi bir sıralama yöntemi kopyalamak için gidiyor IEnumerablebir içine Listsıralayabilir Listve sonra size bir olan sıralı liste dönmek IEnumerablebir yanı sıra IList.

Bu, bir öğesinin "sonsuza kadar devam et" özelliğini kaybettiğiniz anlamına gelir IEnumerable, ancak daha sonra böyle bir özelliği sıralayamazsınız.


7
Kesinlikle doğru. IEnumerable'ın amacı, "sonraki" öğeyi istemeye devam ederek, baştan sona yineleyebileceğiniz bir seriyi tanıtmaktır. Bu, tüm içerik bilinmeden önce bir IEnumerable'ın kısmen yinelenebileceği anlamına gelir; sahip olana kadar bunların hepsini ne zaman yaşadığınızı bilmek zorunda değilsiniz. Sıralama (Linq'in yapmanıza izin verdiği birçok şey gibi) sıralı bir liste olarak dizinin tamamı hakkında bilgi sahibi olmayı gerektirir; sıralı bir dizide ilk görünen öğe, bir dizi tarafından döndürülen son öğe olabilir ve tüm öğelerin ne olduğunu bilmediğiniz sürece bunu bilemezsiniz.
KeithS


2

Her zaman yerinde yapamayız, ancak mümkün olduğunda tespit ederiz:

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

Bu, aşağıdaki kullanışlı yapıyı kullanır:

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

Bunu tavsiye edersem emin değilim. Bir IEnumerable <T> 'niz varsa, ancak uygulayan gerçek türü bilmiyorsanız, muhtemelen onu değiştirmemelisiniz. Btw, Array.FunctorComparer <T> dahili.
dtb

Sahip olduğumuz şeyi değiştirirken, yerinde arama sorusunda bunun ima edilmesini sağladım; bunu ima ediyor. Bu, yöntem adında "InPlaceInCan" olması için bir neden; yöntem adları, riskler konusunda en iyi belgelerden daha açık olabilir;) Evet, Array.FunctorComparer <T> dahili, ancak önemsiz. Bunu, "yardımcı sınıflar setinizde sahip olduğunuz functor karşılaştırıcınız" örneğinde düşünebileceğim en iyi yol olduğu için koydum.
Jon Hanna

@dtb ikinci düşüncelerimi kullanmak için değiştirildi (Array.FunctorComparer'a tekrar bir göz attım ve yine de benimkini tercih ediyorum!)
Jon Hanna

Akıllı fikir ve adlandırma! Ama neden çift döküm karşıtı desen de listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);? Ya buna benzemeye ne dersinizlistToSort = (src as List<T>); if (null == listToSort) listToSort = new List<T>(src);
Jeroen Wiert Pluimers

1
@JeroenWiertPluimers her zaman örnek kodla ilgili bir sorun vardır; belkide yukarıdakiler biraz daha kısa olduğu için uğraşmadım ve konuya konsantre olmak istedim, ancak örneklerde bile kötü alışkanlıklardan vazgeçmek iyidir.
Jon Hanna
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.