के साथ एक संग्रह पेजिंग आप LINQ में संग्रह के माध्यम से कैसे पृष्ठ देखते हैं कि आपके पास startIndex
और count
है?LINQ
LINQ
उत्तर
कुछ महीने वापस मैं जो IQueryable<T>
और एक अन्य वर्ग पर एक विस्तार विधि का इस्तेमाल किया एक LINQ संग्रह paginating के निम्नलिखित प्राकृतिक तरीके से उपलब्ध कराने के लिए सुविज्ञ इंटरफेस और 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
खुद पेजिंग को लागू करने की कर रहे हैं।
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);
}
स्पष्टीकरण:: तथ्य की बात के रूप में, यह LINQ-एल्गोरिथ्म ऊपर दिखाए गए के रूप में सरल है, लेकिन अधिक performant एक "व्यापक तरीके से" में एक से अधिक बार के लिए 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>
)। आप एक अतिरिक्त संग्रह के रूप में प्रत्येक पृष्ठ को संभालने के लिए है, लेकिन जैसे
IEnumerable<IEnumerable<Item>> pageRange
.Select((page, index) =>
myItems
.Skip(index*PageSize)
.Take(PageSize));
बेशक: यह आप इसे कैसे Skip
और Take
का उपयोग कर एक साथ कर सकते हैं pageRange
ऊपर बनाया से सूचकांक चयन करने के साथ है यदि आप दोहराना शुरू कर रहे हैं तो यह वास्तव में संभालना आसान है।
एक लाइनर 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
}
}
मुझे विश्वास है कि यह कुछ इस तरह करने के लिए ठीक है। उसके पास जवाब हो सकता है लेकिन शायद वह देखना चाहता है कि अन्य लोग भी साथ आ सकते हैं। –
यह मूल रूप से स्टैक ओवरफ्लो की बीटा अवधि के पहले दिन पोस्ट किया गया था, इस प्रकार लेख आईडी के लिए 66। मैं जेफ के लिए सिस्टम का परीक्षण कर रहा था। इसके अलावा यह सामान्य परीक्षण बकवास की बजाय उपयोगी जानकारी की तरह लग रहा था जो कभी-कभी बीटा परीक्षण से बाहर आता है। –