Nasıl C # bir listenin ilk N unsurları almak için?


384

Projemdeki bir otobüs tarifesini sorgulamak için Linq'i kullanmak istiyorum, böylece herhangi bir zamanda sonraki 5 otobüs varış saatini alabilirim. Sorgumu ilk 5 sonuçla nasıl sınırlandırabilirim?

Daha genel olarak, C # 'daki listeden nasıl bir dilim alabilirim? (Python'da mylist[:5]ilk 5 unsuru almak için kullanırdım .)

Yanıtlar:


706
var firstFiveItems = myList.Take(5);

Veya dilimlemek için:

var secondFiveItems = myList.Skip(5).Take(5);

Ve elbette, ilk beş öğeyi bir tür siparişe göre almak uygundur:

var firstFiveArrivals = myList.OrderBy(i => i.ArrivalTime).Take(5);

87
Listede yalnızca 3 öğe varsa istisna oluşturur mu? Yoksa en fazla 5 tane alacak mı?
bobek

87
@bobek: Bir istisna oluşturmaz. Yeterli öğe yoksa, sahip olduğu şeyi döndürür.
Joshua Pech

1
tam olarak, herhangi bir istisna atılmadı atla ve birleştir kombine sorunumu çözdüğüm için, herhangi bir genel koleksiyon almak ve toplu iş başına x ürün işlemek
JohanLarsson

Bu unutulmamalıdır .Take(n)döner bir TakeIterator; içinde nöğeler bulunan bir liste döndürmez (çoğunun kullanılabilir olduğu varsayılarak). Somut bir dizi veya liste almak için .ToArray()veya .ToList()sonucunu kullanın Take.
Andrew Webb

69

Herkes ilgileniyorsa (soru bu sürümü sormasa bile), C # 2'de olurdu: (Bazı önerileri izleyerek cevabı düzenledim)

myList.Sort(CLASS_FOR_COMPARER);
List<string> fiveElements = myList.GetRange(0, 5);

Belki de isimsiz bir yüklem ekleyin?
AlexeyMK

2
Liste <T> .Sort geçersizdir; sıralamanız ve ardından GetRange'ı ayrı ayrı kullanmanız gerekir. CLASS_FOR_COMPARER gereksinimini ortadan kaldırmak için bir Karşılaştırma <T> anonim yöntemi de kullanabilirsiniz.
Marc Gravell

@AlexeyMK - bir Karşılaştırma <T> demek, bir yüklem değil (Tahmin <T>) - verileri filtrelemek için bir yüklem kullanılır
Marc Gravell

Bu cevabın şimdi, 10 yıl ve birçok C # sürümünde bile faydalı olduğuna inanıyorum. Listeniz olan özel durum için. Özellikle birçok öğeyi atlıyorsanız. Örneğin, bir milyon öğeden oluşan bir listeniz var ve listenin en çok 5'inden oluşan bir dilim istiyorsunuz. GetRange onları nereye götüreceğini tam olarak bilir. Skip+ Take'In akıllı olup olmadığını veya atlanan öğelerin üzerinde numaralanıp numaralanmadığını bilmiyorum . Ve bilmeme gerek yok - sadece GetRange kullanıyorum (bir liste verildiğinde). Sadece ikinci parametrenin sayıldığından emin olun ( son dizin yerine ).
ToolmakerSteve

Bununla ilgili güzel olan şey .Take(n), nüzerinde çalıştığı sırada daha az eleman varsa endişelenmenize gerek olmamasıdır . Sorun List<T>.GetRange(0, count)şu ki, endişelenmek zorunda .... öğeleri ArgumentExceptionyoksa bir alacaksınız count.
Andrew Webb

5

Gibi paginationEğer çekimi için formule aşağıda kullanabilirsiniz slice of list or elements:

var slice = myList.Skip((pageNumber - 1) * pageSize)
                  .Take(pageSize);

Örnek 1: İlk beş madde

var pageNumber = 1;
var pageSize = 5;

Örnek 2: İkinci beş madde

var pageNumber = 2;
var pageSize = 5;

Örnek 3: Üçüncü beş madde

var pageNumber = 3;
var pageSize = 5;

Formül parametrelerine dikkat edilirse pageSize = 5ve pageNumberdeğişiyorsa, dilimlemedeki öğe sayısını değiştirmek isterseniz değiştirin pageSize.


1

İlk 5 öğeyi daha iyi almak için, bunun gibi ifadeyi kullanın:

var firstFiveArrivals = myList.Where([EXPRESSION]).Take(5);

veya

var firstFiveArrivals = myList.Where([EXPRESSION]).Take(5).OrderBy([ORDER EXPR]);

Varyanttan daha hızlı olacaktır, çünkü LINQ motoru gecikmeli yürütme nedeniyle tüm listeyi taramayacak ve tüm dizileri sıralamayacaktır.

class MyList : IEnumerable<int>
{

    int maxCount = 0;

    public int RequestCount
    {
        get;
        private set;
    }
    public MyList(int maxCount)
    {
        this.maxCount = maxCount;
    }
    public void Reset()
    {
        RequestCount = 0;
    }
    #region IEnumerable<int> Members

    public IEnumerator<int> GetEnumerator()
    {
        int i = 0;
        while (i < maxCount)
        {
            RequestCount++;
            yield return i++;
        }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    #endregion
}
class Program
{
    static void Main(string[] args)
    {
        var list = new MyList(15);
        list.Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 5;

        list.Reset();
        list.OrderBy(q => q).Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 15;

        list.Reset();
        list.Where(q => (q & 1) == 0).Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 9; (first 5 odd)

        list.Reset();
        list.Where(q => (q & 1) == 0).Take(5).OrderBy(q => q).ToArray();
        Console.WriteLine(list.RequestCount); // 9; (first 5 odd)
    }
}

25
Tek yapmanız gereken, seçtikten sonra yalnızca ilk 5 öğeyi sipariş etmek. Daha hızlı olabilir, ancak aynı zamanda insanların gerçekte elde etmek istedikleri şey olma olasılıkları daha düşük olan farklı anlambilime de sahiptir.
Greg Beech
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.