Làm thế nào để có được N phần tử đầu tiên của danh sách trong C #?


384

Tôi muốn sử dụng Linq để truy vấn lịch trình xe buýt trong dự án của mình, để bất cứ lúc nào tôi cũng có thể nhận được 5 lần xe buýt tiếp theo. Làm cách nào tôi có thể giới hạn truy vấn của mình trong 5 kết quả đầu tiên?

Tổng quát hơn, làm thế nào tôi có thể lấy một lát danh sách trong C #? (Trong Python tôi sẽ sử dụng mylist[:5]để có được 5 phần tử đầu tiên.)

Câu trả lời:


708
var firstFiveItems = myList.Take(5);

Hoặc để cắt:

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

Và tất nhiên thường là thuận tiện để có được năm mặt hàng đầu tiên theo một số thứ tự:

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

87
Liệu nó có ném ngoại lệ nếu chỉ có 3 ví dụ trong danh sách không? Hoặc sẽ mất nhiều như có đến 5?
bobek

87
@bobek: Nó không ném ngoại lệ. Nó chỉ đơn giản trả về những gì nó có nếu không có đủ các yếu tố.
Joshua Pech

1
chính xác, không có trường hợp ngoại lệ nào được bỏ qua Bỏ qua và kết hợp đã giải quyết vấn đề của tôi vì tôi muốn lấy bất kỳ bộ sưu tập chung nào và xử lý x vật phẩm mỗi đợt
JohanLarsson

Cần lưu ý rằng .Take(n)trả về một TakeIterator; nó không trả về một danh sách có ncác phần tử trong đó (giả sử rằng có nhiều phần tử có sẵn). Sử dụng .ToArray()hoặc .ToList()trên kết quả của Takeđể có được một mảng hoặc danh sách cụ thể.
Andrew Webb

69

Trong trường hợp bất kỳ ai cũng quan tâm (ngay cả khi câu hỏi không yêu cầu phiên bản này), trong C # 2 sẽ là: (Tôi đã chỉnh sửa câu trả lời, theo một số gợi ý)

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

Có thể thêm một vị ngữ ẩn danh là tốt?
AlexeyMK

2
Danh sách <T> .Sort trả về void; bạn sẽ cần sắp xếp, sau đó sử dụng GetRange riêng. Bạn cũng có thể sử dụng phương pháp so sánh <T> so sánh để loại bỏ sự cần thiết của CLASS_FOR_COMPARER.
Marc Gravell

@AlexeyMK - ý bạn là So sánh <T>, không phải là vị ngữ (Vị ngữ <T>) - một vị ngữ được sử dụng để lọc dữ liệu
Marc Gravell

Tôi tin rằng câu trả lời này hữu ích ngay cả bây giờ, 10 năm và nhiều phiên bản C # sau này. Đối với trường hợp cụ thể mà bạn có một danh sách. Đặc biệt nếu bạn đang bỏ qua nhiều mặt hàng. Ví dụ: bạn có một danh sách gồm một triệu mặt hàng và bạn muốn có một lát gồm 5 mặt hàng, nằm xa trong danh sách. GetRange biết chính xác nơi để đi để lấy chúng. Tôi không biết liệu Skip+ Takecó thông minh hay không, hay liệu nó có liệt kê các mục bị bỏ qua hay không. Và tôi không cần biết - Tôi chỉ sử dụng GetRange (khi được cung cấp Danh sách). Chỉ cần chắc chắn rằng bạn nhận ra tham số thứ hai là số đếm (thay vì chỉ số cuối cùng ).
ToolmakerSteve

Điều tuyệt vời .Take(n)là bạn không phải lo lắng nếu có ít hơn ncác yếu tố trong chuỗi hoạt động. Vấn đề với List<T>.GetRange(0, count)là bạn phải lo lắng .... bạn sẽ nhận được ArgumentExceptionnếu không có countvật phẩm.
Andrew Webb

5

Giống như paginationbạn có thể sử dụng công thức dưới đây để dùng slice of list or elements:

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

Ví dụ 1: năm mục đầu tiên

var pageNumber = 1;
var pageSize = 5;

Ví dụ 2: năm mục thứ hai

var pageNumber = 2;
var pageSize = 5;

Ví dụ 3: năm mục thứ ba

var pageNumber = 3;
var pageSize = 5;

Nếu thông báo về các tham số định dạng pageSize = 5pageNumberđang thay đổi, nếu bạn muốn thay đổi số lượng vật phẩm trong lát cắt, bạn thay đổi pageSize.


1

Để có 5 yếu tố đầu tiên tốt hơn sử dụng biểu thức như thế này:

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

hoặc là

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

Nó sẽ nhanh hơn biến thể orderBy, bởi vì công cụ LINQ sẽ không quét tất cả danh sách do thực thi bị trì hoãn và sẽ không sắp xếp tất cả các mảng.

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
Ngoại trừ việc bạn hiện chỉ đặt hàng 5 yếu tố đầu tiên sau khi bạn đã chọn chúng. Nó có thể nhanh hơn, nhưng nó cũng có ngữ nghĩa khác nhau, ít có khả năng là những gì mọi người thực sự muốn đạt được.
Greg Beech
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.