आप LINQ में दिए गए संग्रह के माध्यम से कैसे पृष्ठ देखते हैं कि आपके पास a startIndex
और a है count
?
आप LINQ में दिए गए संग्रह के माध्यम से कैसे पृष्ठ देखते हैं कि आपके पास a startIndex
और a है count
?
जवाबों:
कुछ महीने पहले मैंने धाराप्रवाह इंटरफेस और LINQ के बारे में एक ब्लॉग पोस्ट लिखा था जिसमें IQueryable<T>
एक LINQ संग्रह को पृष्ठांकित करने का निम्नलिखित प्राकृतिक तरीका प्रदान करने के लिए एक एक्सटेंशन विधि और दूसरी कक्षा का उपयोग किया गया था।
var query = from i in ideas
select i;
var pagedCollection = query.InPagesOf(10);
var pageOfIdeas = pagedCollection.Page(2);
आप MSDN कोड गैलरी पेज से कोड प्राप्त कर सकते हैं: पाइपलाइन, फिल्टर, धाराप्रवाह एपीआई और LINQ से SQL ।
यह Skip
और Take
विस्तार विधियों के साथ बहुत सरल है ।
var query = from i in ideas
select i;
var paggedCollection = query.Skip(startIndex).Take(count);
मैंने इसे थोड़ा अलग तरीके से हल किया है कि दूसरों के पास क्या है जैसा कि मुझे एक पुनरावर्तक के साथ अपना पैजेंटिनेटर बनाना था। इसलिए मैंने पहले उन वस्तुओं के संग्रह के लिए पृष्ठ संख्याओं का एक संग्रह बनाया जो मेरे पास हैं:
// 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
}
}
यह प्रश्न कुछ पुराना है, लेकिन मैं अपने पेजिंग एल्गोरिथ्म को पोस्ट करना चाहता था जो पूरी प्रक्रिया (उपयोगकर्ता इंटरैक्शन सहित) दिखाता है।
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-30 से पहले पुनरावृत्त होने से पहले 10-30 के सभी साइड इफेक्ट्स दिखाई देंगे। वेरिएंट IEnumerable
सीधे इंटरफ़ेस का उपयोग करने के बजाय, अंतिम तार्किक पृष्ठ के अंत की स्थिति को याद रखेगा, इसलिए कोई स्पष्ट लंघन की आवश्यकता नहीं है और दुष्प्रभाव दोहराए नहीं जाएंगे।