Làm cách nào để trang của bạn thông qua bộ sưu tập trong LINQ do bạn có startIndex
và count
?Phân trang bộ sưu tập với LINQ
Trả lời
Một vài tháng trở lại tôi đã viết một bài đăng blog về thạo giao diện và LINQ mà đã sử dụng một phương pháp mở rộng trên IQueryable<T>
và lớp khác để cung cấp các cách tự nhiên sau đây của một bộ sưu tập paginating LINQ.
var query = from i in ideas
select i;
var pagedCollection = query.InPagesOf(10);
var pageOfIdeas = pagedCollection.Page(2);
Bạn có thể lấy mã từ Thư viện mã MSDN Trang: Pipelines, Filters, Fluent API and LINQ to SQL.
Rất đơn giản với các phương pháp mở rộng Skip
và Take
.
var query = from i in ideas
select i;
var paggedCollection = query.Skip(startIndex).Take(count);
Câu hỏi này hơi cũ, nhưng tôi muốn đăng thuật toán phân trang hiển thị toàn bộ quy trình (bao gồm tương tác của người dùng).
const int pageSize = 10;
const int count = 100;
const int startIndex = 20;
int took = 0;
bool getNextPage;
var page = ideas.Skip(startIndex);
do
{
Console.WriteLine("Page {0}:", (took/pageSize) + 1);
foreach (var idea in page.Take(pageSize))
{
Console.WriteLine(idea);
}
took += pageSize;
if (took < count)
{
Console.WriteLine("Next page (y/n)?");
char answer = Console.ReadLine().FirstOrDefault();
getNextPage = default(char) != answer && 'y' == char.ToLowerInvariant(answer);
if (getNextPage)
{
page = page.Skip(pageSize);
}
}
}
while (getNextPage && took < count);
Tuy nhiên, nếu bạn là sau màn trình diễn, và trong mã sản xuất, chúng tôi tất cả sau khi thực hiện, bạn không nên sử dụng phân trang LINQ như trình bày ở trên, mà là tiềm ẩn IEnumerator
để thực hiện phân trang cho mình. Như một vấn đề của thực tế, nó là đơn giản như LINQ-thuật toán trình bày ở trên, nhưng performant hơn:
const int pageSize = 10;
const int count = 100;
const int startIndex = 20;
int took = 0;
bool getNextPage = true;
using (var page = ideas.Skip(startIndex).GetEnumerator())
{
do
{
Console.WriteLine("Page {0}:", (took/pageSize) + 1);
int currentPageItemNo = 0;
while (currentPageItemNo++ < pageSize && page.MoveNext())
{
var idea = page.Current;
Console.WriteLine(idea);
}
took += pageSize;
if (took < count)
{
Console.WriteLine("Next page (y/n)?");
char answer = Console.ReadLine().FirstOrDefault();
getNextPage = default(char) != answer && 'y' == char.ToLowerInvariant(answer);
}
}
while (getNextPage && took < count);
}
Giải thích: Nhược điểm của việc sử dụng Skip()
cho nhiều lần trong một "cách tầng" là, rằng nó sẽ không thực sự lưu trữ "con trỏ" của lần lặp, nơi nó được bỏ qua lần cuối. - Thay vào đó, chuỗi gốc sẽ được tải trước bằng các cuộc gọi bỏ qua, điều này sẽ dẫn đến việc "tiêu thụ" các trang "đã tiêu thụ" đã hết lần này đến lần khác. - Bạn có thể chứng minh rằng bản thân bạn, khi bạn tạo chuỗi ideas
để nó mang lại hiệu ứng phụ. -> Ngay cả khi bạn đã bỏ qua 10-20 và 20-30 và muốn xử lý 40+, bạn sẽ thấy tất cả các tác dụng phụ của 10-30 được thực thi lại, trước khi bạn bắt đầu lặp lại 40+. Biến thể sử dụng trực tiếp giao diện của IEnumerable
, thay vào đó sẽ nhớ vị trí của phần cuối của trang logic cuối cùng, do đó không cần bỏ qua rõ ràng và các hiệu ứng phụ sẽ không được lặp lại.
Tôi đã giải quyết vấn đề này một chút khác với những gì mà những người khác có khi tôi phải làm người tạo trang riêng của mình, với bộ lặp. Vì vậy, trước tiên tôi đã tạo một tập hợp số trang cho bộ sưu tập các mục mà tôi có:
// assumes that the item collection is "myItems"
int pageCount = (myItems.Count + PageSize - 1)/PageSize;
IEnumerable<int> pageRange = Enumerable.Range(1, pageCount);
// pageRange contains [1, 2, ... , pageCount]
Sử dụng điều này tôi có thể dễ dàng phân chia bộ sưu tập mục thành tập hợp "trang". Một trang trong trường hợp này chỉ là một tập hợp các mục (IEnumerable<Item>
). Đây là cách bạn có thể làm điều đó bằng Skip
và Take
cùng với việc lựa chọn các chỉ số từ pageRange
tạo ở trên:
IEnumerable<IEnumerable<Item>> pageRange
.Select((page, index) =>
myItems
.Skip(index*PageSize)
.Take(PageSize));
Tất nhiên bạn phải xử lý mỗi trang như một bộ sưu tập thêm nhưng ví dụ nếu bạn đang làm tổ lặp lại thì điều này thực sự dễ xử lý.
Các một liner TLDR phiên bản sẽ là:
var pages = Enumerable
.Range(0, pageCount)
.Select((index) => myItems.Skip(index*PageSize).Take(PageSize));
Mà có thể được sử dụng như thế này:
for (Enumerable<Item> page : pages)
{
// handle page
for (Item item : page)
{
// handle item in page
}
}
- 1. LINQ GroupBy bộ sưu tập
- 2. Làm cách nào để sử dụng LINQ để phân trang một bộ sưu tập chung?
- 3. LINQ hiệu suất cho bộ sưu tập
- 4. Bộ sưu tập được phân trang trong Backbone.js
- 5. Intersect một tập hợp các bộ sưu tập trong LINQ
- 6. Cách hợp nhất một bộ sưu tập các bộ sưu tập trong LINQ
- 7. Sắp xếp bộ sưu tập trong bộ sưu tập bằng cách sử dụng LINQ
- 8. LINQ - bộ sưu tập bộ lọc trẻ em
- 9. LINQ để cập nhật bộ sưu tập với các giá trị từ một bộ sưu tập khác?
- 10. Hiệu suất LINQ cho Bộ sưu tập Lớn
- 11. WPF: Bộ sưu tập liên kết với Bộ sưu tập vào một ListBox với các nhóm
- 12. Làm thế nào tôi có thể làm phân trang với bộ sưu tập @OneToMany
- 13. bộ sưu tập với lambdaj
- 14. Bộ sưu tập với generics
- 15. LINQ Ring: Any() vs Contains() cho Bộ sưu tập lớn
- 16. Bộ sưu tập để chuỗi sử dụng LINQ
- 17. Đếm từ trong bộ sưu tập bằng LINQ
- 18. Return Thuộc tính cho Bộ sưu tập từ LINQ Query
- 19. LINQ: Tìm phần tử trong bộ sưu tập
- 20. LINQ Nhóm By và chọn bộ sưu tập
- 21. Truy vấn Bộ sưu tập Trẻ em trong LINQ
- 22. LINQ chọn các mục từ bộ sưu tập trẻ em
- 23. LINQ: Truy vấn nếu bộ sưu tập chứa bất kỳ phần tử nào trong bộ sưu tập khác
- 24. Phân loại động với LINQ
- 25. LINQ: Tìm kiếm một bộ sưu tập trong một bộ sưu tập cho một đối tượng duy nhất
- 26. Mô hình Backbone.js với bộ sưu tập
- 27. Backbone.js Bộ sưu tập của Bộ sưu tập
- 28. LINQ to Objects Tham gia hai bộ sưu tập để thiết lập giá trị trong bộ sưu tập đầu tiên
- 29. Bộ sưu tập rác
- 30. LINQ và phân trang với một listview
Tôi tin rằng đó là OK để làm một cái gì đó như thế này. Anh ta có thể có một câu trả lời nhưng có lẽ anh ta muốn xem những gì người khác có thể nghĩ ra. –
Điều này ban đầu được đăng trong ngày đầu tiên của giai đoạn beta của StackOverflow, do đó số 66 cho ID bài viết. Tôi đã thử nghiệm hệ thống, cho Jeff. Thêm vào đó nó có vẻ giống như thông tin hữu ích thay vì crap thử nghiệm thông thường mà đôi khi đi ra khỏi thử nghiệm beta. –