Get a page from a collection without going past the last page?
I have a collect开发者_开发技巧ion of items: ICollection<T> MyCollection
I'm wondering if there is a way to get a subcollection of items (paged) without going past the last page... Right now it returns an empty list because I keep going past the available pages.
For example, if MyCollection
has 10 items and I ask for Page 5 (3 items per page) I get an empty collection. Instead, I'd really want the last page (which happens to be page 4, 1 item). Not sure what to do here. If there is a LINQ way of doing this that would rock.
Example variables:
int page = 5;
int itemPerPage = 3;
//MyCollection.Count == 10;
Logic:
// make sure there are any items and that itemsPerPage is greater than zero
// to prevent any DivideByZeroExeceptions from being thrown
if (MyCollection.Any() && itemsPerPage > 0)
{
if (page * itemsPerPage > MyCollection.Count)
{
// if page is past collection change to the last page
page = (int)Math.Ceiling((float)MyCollection.Count / (float)itemsPerPage);
}
else if (page < 1)
{
// if page is before collection change to 1
page = 1;
}
// skip pages and select the number of pages
MyCollection.Skip((page - 1) * itemsPerPage).Take(itemsPerPage);
}
In this case, page = 5
, which is outside of the collection (5 * 3 == 12)
so page gets reset to 10 divided and rounded up by 3 == 4
. Finally it will skip (4 - 1) * 3 == 9
and then take 3
, which will be the last page containing 1
item
I usually put this divide-and-round-up logic into an integer extension method:
public static class IntExtensions
{
public static int DivideByAndRoundUp(this int number, int divideBy)
{
return (int)Math.Ceiling((float)number / (float)divideBy);
}
}
which will let you write page = MyCollection.Count.DivideAndRoundUp(itemsPerPage)
"Pure" LINQ:
var result = (arr.Count > (page - 1) * perPage ?
arr.Skip(perPage * (page - 1)) :
arr.Skip(arr.Count / perPage * perPage))
.Take(perPage);
精彩评论