如果你有一個startIndex
和一個count
,你如何翻閱LINQ中的一個集合?用LINQ分頁集合
回答
幾個月前,我寫了一篇博客文章流利的接口和LINQ其用在IQueryable<T>
和另一個類的擴展方法提供一個分頁LINQ收集以下自然的方式。
var query = from i in ideas
select i;
var pagedCollection = query.InPagesOf(10);
var pageOfIdeas = pagedCollection.Page(2);
你可以從MSDN代碼庫頁的代碼:Pipelines, Filters, Fluent API and LINQ to SQL。
這是非常簡單的Skip
和Take
擴展方法。
var query = from i in ideas
select i;
var paggedCollection = query.Skip(startIndex).Take(count);
這個問題有點舊,但我想發佈我的分頁算法,顯示整個過程(包括用戶交互)。
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);
但是,如果你是演出結束後,並在生產代碼,我們都表現後,你不應該使用LINQ的分頁如上圖所示,而是底層IEnumerator
實現分頁自己。由於事實上,它是如上所示的LINQ算法一樣簡單,但更高性能:
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);
}
說明:使用Skip()
用於在「級聯方式」多次的缺點是,它會沒有真正存儲迭代的「指針」,它在上一次被跳過。 - 相反,原始序列將被前面加載跳過調用,這將導致「消耗」已經「消耗」的頁面一遍又一遍。 - 當您創建序列ideas
時,您可以證明您自己,以便產生副作用。 - >即使你已經跳過了10-20和20-30,並且想要處理40+,在你開始迭代40+之前,你會看到10-30的所有副作用被再次執行。 直接使用IEnumerable
的接口的變體會記住最後一個邏輯頁面末尾的位置,因此不需要顯式跳過,副作用也不會重複。
我解決了這個問題,與其他人有點不同,因爲我必須用一箇中繼器製作我自己的分頁器。所以,我首次提出頁碼的集合,我有項目的集合:
// 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]
使用這個我可以很容易地劃分項目收集到的「頁」的集合。這種情況下的頁面只是一個項目集合(IEnumerable<Item>
)。這是如何使用Skip
和Take
一起做它從上面創建的pageRange
選擇索引:
IEnumerable<IEnumerable<Item>> pageRange
.Select((page, index) =>
myItems
.Skip(index*PageSize)
.Take(PageSize));
當然你必須處理每一頁作爲一個額外的集合,但如如果你正在嵌套中繼器,那麼這實際上很容易處理。
的一個班輪TLDR版本是這樣的:
var pages = Enumerable
.Range(0, pageCount)
.Select((index) => myItems.Skip(index*PageSize).Take(PageSize));
哪些可以作爲這樣的:
for (Enumerable<Item> page : pages)
{
// handle page
for (Item item : page)
{
// handle item in page
}
}
- 1. 用LINQ拆分集合
- 2. LINQ:分組集合
- 3. 如何使用Linq來分頁泛型集合?
- 4. 使用linq合併集合
- 5. 用linq查詢集合的子集合
- 6. 使用Linq查詢集合集合
- 7. LINQ從集合
- 8. Rails緩存分頁集合
- 9. Backbone.js中的分頁集合
- 10. LINQ,聯接,分組和集合
- 11. 使用LINQ映射集合
- 12. 使用Marionette.js分頁裝飾集合
- 13. 高效分頁大型數據集LINQ
- 14. 行走嵌套集合結合分頁
- 15. Laravel分頁與水合模型集合
- 16. LINQ嵌套集合
- 17. VB.NET LINQ - 集合中的集合計數?
- 18. 閱讀集合在linq集合內
- 19. LINQ JOIN集合中的集合
- 20. Linq where集合中的集合條款
- 21. LINQ和分頁
- 22. 通用父集合拆分子集合
- 23. 使用LINQ進行分頁?
- 24. LINQ到SQL/LINQ到集合性能
- 25. 使用linq獲取逗號分隔的實體集合清單
- 26. 使用Linq將平坦表結果分解爲對象集合
- 27. 使用Linq將列表拆分成集合
- 28. Linq使用另一個集合中的值更新集合?
- 29. 如何使用LINQ訂購集合及其子集合?
- 30. 如何使用LINQ在集合中選擇集合?
我認爲,這是確定做這樣的事情。他可能有一個答案,但也許他想看看其他人也可以提出什麼。 – 2008-11-29 03:39:50