visit
The Paging or Partitioning concept is used in many fields. When you have a set of items and you want to divide them equally between some sort of containers or groups, you are thinking of paging or partitioning but maybe you don’t recognize it, yet…
Now, we want to divide these 10 items into groups where each group contains 3 items.
Let me explain; when you divide the Item Zero-Index on the Page Size, you get two things:
Item Zero-Index = (Page Zero-Index * Page Size) + (Item Zero-Index Per Page)
This means that if we have a value for Page Zero-Index, and a value for Page Size, and we need to know the Zero-Index of the first item and the last item on this page, we can use the equation above as follows.
**First Item Zero-Index
\ = (Page Zero-Index * Page Size) + Minimum (Item Zero-Index Per Page)
= (Page Zero-Index * Page Size) + 0
= (Page Zero-Index * Page Size)
**Last Item Zero-Index
\ = (Page Zero-Index * Page Size) + Maximum (Item Zero-Index Per Page)
= (Page Zero-Index * Page Size) + (Page Size — 1)
But note that if the calculated Last Item Zero-Index is greater than the index of the last item in the whole collection, then take the smaller number which is the index of the last item in the whole collection.
Having all the equations proved, let’s see how to apply them in code. I will provide two implementations, one in JavaScript, and the other one in .NET C#.
Applying the equations in the form of an extension function to the JavaScript Array.
Array.prototype.page = function(pageSize){
const self = this;
let actualPageSize = pageSize;
if(actualPageSize <= 0) {
actualPageSize = self.length;
}
let maxNumberOfPages = Math.max(1, Math.ceil(parseFloat(parseFloat(self.length) / parseFloat(actualPageSize))));
let pagesBoundries = {};
for(let pageZeroIndex = 0; pageZeroIndex < maxNumberOfPages; pageZeroIndex++) {
pagesBoundries[pageZeroIndex] = {
firstItemZeroIndex: (pageZeroIndex * actualPageSize),
lastItemZeroIndex: Math.min((pageZeroIndex * actualPageSize) + (actualPageSize - 1), self.length - 1)
};
}
return {
actualPageSize: actualPageSize,
numberOfPages: maxNumberOfPages,
pagesBoundries: pagesBoundries,
find: function(itemZeroIndex) {
return {
pageZeroIndex: parseInt(parseInt(itemZeroIndex) / parseInt(actualPageSize)),
itemZeroIndexInsidePage: parseInt(parseInt(itemZeroIndex) % parseInt(actualPageSize))
};
}
};
};
let items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let pagingResult = items.page(3);
console.log(pagingResult);
console.log(pagingResult.find(0)); // { pageZeroIndex: 0, itemZeroIndexInsidePage: 0 }
console.log(pagingResult.find(1)); // { pageZeroIndex: 0, itemZeroIndexInsidePage: 1 }
console.log(pagingResult.find(2)); // { pageZeroIndex: 0, itemZeroIndexInsidePage: 2 }
console.log(pagingResult.find(3)); // { pageZeroIndex: 1, itemZeroIndexInsidePage: 0 }
console.log(pagingResult.find(4)); // { pageZeroIndex: 1, itemZeroIndexInsidePage: 1 }
console.log(pagingResult.find(5)); // { pageZeroIndex: 1, itemZeroIndexInsidePage: 2 }
console.log(pagingResult.find(6)); // { pageZeroIndex: 2, itemZeroIndexInsidePage: 0 }
console.log(pagingResult.find(7)); // { pageZeroIndex: 2, itemZeroIndexInsidePage: 1 }
console.log(pagingResult.find(8)); // { pageZeroIndex: 2, itemZeroIndexInsidePage: 2 }
console.log(pagingResult.find(9)); // { pageZeroIndex: 3, itemZeroIndexInsidePage: 0 }
Applying the equations in the form of an extension method to the .NET C# List.
public delegate ItemPosition FindItemPositionHandler(int itemZeroIndex);
public class PagingDescriptor
{
public int ActualPageSize { get; private set; }
public int NumberOfPages { get; private set; }
public PageBoundry[] PagesBoundries { get; private set; }
public FindItemPositionHandler Find { get; private set; }
public PagingDescriptor(
int actualPageSize,
int numberOfPages,
PageBoundry[] pagesBoundries,
FindItemPositionHandler find)
{
ActualPageSize = actualPageSize;
NumberOfPages = numberOfPages;
PagesBoundries = pagesBoundries;
Find = find;
}
}
public class PageBoundry
{
public int FirstItemZeroIndex { get; private set; }
public int LastItemZeroIndex { get; private set; }
public PageBoundry(int firstItemZeroIndex, int lastItemZeroIndex)
{
FirstItemZeroIndex = firstItemZeroIndex;
LastItemZeroIndex = lastItemZeroIndex;
}
}
public class ItemPosition
{
public int PageZeroIndex { get; private set; }
public int ItemZeroIndexInsidePage { get; private set; }
public ItemPosition(int pageZeroIndex, int itemZeroIndexInsidePage)
{
PageZeroIndex = pageZeroIndex;
ItemZeroIndexInsidePage = itemZeroIndexInsidePage;
}
}
public static class ListExtensionMethods
{
public static PagingDescriptor Page(this IList list, int pageSize)
{
var actualPageSize = pageSize;
if (actualPageSize <= 0)
{
actualPageSize = list.Count;
}
var maxNumberOfPages = (int)Math.Round(Math.Max(1, Math.Ceiling(((float)list.Count) / ((float)actualPageSize))));
return new PagingDescriptor(
actualPageSize,
maxNumberOfPages,
Enumerable
.Range(0, maxNumberOfPages)
.Select(pageZeroIndex => new PageBoundry(
pageZeroIndex * actualPageSize,
Math.Min((pageZeroIndex * actualPageSize) + (actualPageSize - 1), list.Count - 1)
)).ToArray(),
(itemZeroIndex) => new ItemPosition(
itemZeroIndex / actualPageSize,
itemZeroIndex % actualPageSize
)
);
}
}
var items = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var pagingDescriptor = items.Page(3);
var itemPosition01 = pagingDescriptor.Find(0); // { PageZeroIndex = 0, ItemZeroIndexInsidePage = 0 }
var itemPosition02 = pagingDescriptor.Find(1); // { PageZeroIndex = 0, ItemZeroIndexInsidePage = 1 }
var itemPosition03 = pagingDescriptor.Find(2); // { PageZeroIndex = 0, ItemZeroIndexInsidePage = 2 }
var itemPosition04 = pagingDescriptor.Find(3); // { PageZeroIndex = 1, ItemZeroIndexInsidePage = 0 }
var itemPosition05 = pagingDescriptor.Find(4); // { PageZeroIndex = 1, ItemZeroIndexInsidePage = 1 }
var itemPosition06 = pagingDescriptor.Find(5); // { PageZeroIndex = 1, ItemZeroIndexInsidePage = 2 }
var itemPosition07 = pagingDescriptor.Find(6); // { PageZeroIndex = 2, ItemZeroIndexInsidePage = 0 }
var itemPosition08 = pagingDescriptor.Find(7); // { PageZeroIndex = 2, ItemZeroIndexInsidePage = 1 }
var itemPosition09 = pagingDescriptor.Find(8); // { PageZeroIndex = 2, ItemZeroIndexInsidePage = 2 }
var itemPosition10 = pagingDescriptor.Find(9); // { PageZeroIndex = 3, ItemZeroIndexInsidePage = 0 }
Console.WriteLine($"PageZeroIndex: {itemPosition01.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition01.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition02.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition02.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition03.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition03.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition04.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition04.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition05.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition05.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition06.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition06.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition07.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition07.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition08.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition08.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition09.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition09.ItemZeroIndexInsidePage}");
Console.WriteLine($"PageZeroIndex: {itemPosition10.PageZeroIndex}, ItemZeroIndexInsidePage: {itemPosition10.ItemZeroIndexInsidePage}");
Also Published here