Bagaimana cara mendapatkan elemen N pertama dari daftar di C #?


384

Saya ingin menggunakan Linq untuk menanyakan jadwal bus di proyek saya, sehingga kapan saja saya bisa mendapatkan 5 kali kedatangan bus berikutnya. Bagaimana saya bisa membatasi permintaan saya ke 5 hasil pertama?

Secara umum, bagaimana saya bisa mengambil sepotong daftar di C #? (Dengan Python saya akan gunakan mylist[:5]untuk mendapatkan 5 elemen pertama.)

Jawaban:


709
var firstFiveItems = myList.Take(5);

Atau untuk mengiris:

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

Dan tentu saja seringkali lebih mudah untuk mendapatkan lima item pertama sesuai dengan beberapa jenis pesanan:

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

87
Apakah ada pengecualian jika hanya ada, misalnya, 3 item dalam daftar? Atau akankah dibutuhkan sebanyak 5?
— bobek

87
@bobek: Tidak ada pengecualian. Ini hanya mengembalikan apa yang dimilikinya jika tidak ada cukup elemen.
— Joshua Pech

1
tepatnya, tidak ada pengecualian yang dilemparkan Lewati dan Ambil gabungan memecahkan masalah saya karena saya ingin mengambil koleksi generik dan memproses x item per batch
— JohanLarsson

Perlu dicatat bahwa .Take(n)mengembalikan TakeIterator; itu tidak mengembalikan daftar dengan nelemen di dalamnya (dengan asumsi bahwa banyak yang tersedia). Gunakan .ToArray()atau .ToList()pada hasil Takeuntuk mendapatkan array atau daftar konkret.
— Andrew Webb

69

Jika ada yang tertarik (walaupun pertanyaannya tidak menanyakan versi ini), dalam C # 2 adalah: (Saya telah mengedit jawabannya, mengikuti beberapa saran)

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

Mungkin menambahkan predikat anonim juga?
— AlexeyMK

2
Daftar <T> .Sort mengembalikan batal; Anda perlu menyortir, lalu gunakan GetRange secara terpisah. Anda juga bisa menggunakan metode anonim Perbandingan <T> untuk menghapus kebutuhan CLASS_FOR_COMPARER.
— Marc Gravell

@AlexeyMK - maksud Anda adalah Perbandingan <T>, bukan predikat (Predikat <T>) - predikat digunakan untuk memfilter data
— Marc Gravell

Saya percaya jawaban ini berguna bahkan sekarang, 10 tahun dan banyak versi C # kemudian. Untuk kasus khusus di mana Anda memiliki daftar. Apalagi jika Anda melewatkan banyak item. Misalnya Anda memiliki daftar satu juta item, dan Anda ingin sepotong 5 dari mereka, jauh ke dalam daftar. GetRange tahu persis ke mana harus pergi untuk mengambilnya. Saya tidak tahu apakah Skip+ Takesama pintarnya, atau apakah ia menyebutkan item yang dilompati. Dan saya tidak perlu tahu - Saya hanya menggunakan GetRange (ketika diberi Daftar). Pastikan Anda menyadari bahwa parameter kedua adalah jumlah (bukan indeks terakhir ).
— ToolmakerSteve

Yang menyenangkan tentang itu .Take(n)adalah Anda tidak perlu khawatir jika ada kurang dari nelemen dalam urutannya. Masalahnya List<T>.GetRange(0, count)adalah Anda harus khawatir .... Anda akan mendapatkan ArgumentExceptionjika tidak ada countbarang.
— Andrew Webb

5

Seperti paginationAnda dapat menggunakan formule di bawah ini untuk mengambil slice of list or elements:

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

Contoh 1: lima item pertama

var pageNumber = 1;
var pageSize = 5;

Contoh 2: lima item kedua

var pageNumber = 2;
var pageSize = 5;

Contoh 3: lima item ketiga

var pageNumber = 3;
var pageSize = 5;

Jika memperhatikan parameter formule pageSize = 5dan pageNumberberubah, jika Anda ingin mengubah jumlah item dalam mengiris Anda berubah pageSize.


1

Untuk mengambil 5 elemen pertama lebih baik gunakan ekspresi seperti ini:

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

atau

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

Ini akan lebih cepat daripada varian OrderBy, karena mesin LINQ tidak akan memindai melalui semua daftar karena eksekusi tertunda, dan tidak akan mengurutkan semua array.

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
Kecuali bahwa Anda sekarang memesan hanya 5 elemen pertama setelah Anda memilihnya. Mungkin lebih cepat, tetapi juga memiliki semantik yang berbeda, yang cenderung menjadi apa yang orang ingin capai.
— Greg Beech
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.