paint-brush
The Main Equations That Can Make Paging/Partitioning Easyby@ahmedtarekhasan
268 reads

The Main Equations That Can Make Paging/Partitioning Easy

by Ahmed Tarek HasanJanuary 9th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Learn paging/partitioning mathematical equations and how to apply them in JavaScript and.NET C# code. Explaining some mathematical equations which can make it easy for you to implement the paging or partitioning concept. Providing some code examples of how to implement paging.
featured image - The Main Equations That Can Make Paging/Partitioning Easy
Ahmed Tarek Hasan HackerNoon profile picture

Learn paging/partitioning mathematical equations and how to apply them in JavaScript and .NET C# code.


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…


The main goals of this article are to:

  1. Explain some mathematical equations which can make it easy for you to implement the paging or partitioning concept.
  2. Provide some code examples of how to implement paging.

Photo by Jessica Tan on Unsplash

Disclaimer

  1. If you are expecting to find explanations for the paging concept on specific applications like operating systems memory management or file system,… then you are reading the wrong article.
  2. Whenever “Page” or “Paging” is mentioned, “Partition” and “Partitioning” would be valid. Therefore, for brevity, I will use “Page” and “Paging”.

Photo by Sigmund on Unsplash

Back to Basics

The best way to explain paging is to apply to an example. Let’s assume that we have a collection of 10 items, any kind of items, maybe bottles, pencils, bananas… whatever makes you happy.


Now, we want to divide these 10 items into groups where each group contains 3 items.


If we do this manually, we will have the items distributed as in the image below.


Image by Ahmed Tarek


This was easy, right?


Let’s explain what we have in the table above.

  1. The First item, holding 0 as its Zero-Index, would be found at the 0 Zero-Index position, inside the page of 0 Zero-Index.
  2. The Second item, holding 1 as its Zero-Index, would be found at the 1 Zero-Index position, inside the page of 0 Zero-Index.
  3. The Third item, holding 2 as its Zero-Index, would be found at the 2 Zero-Index position, inside the page of 0 Zero-Index.
  4. The Fourth item, holding 3 as its Zero-Index, would be found at the 0 Zero-Index position, inside the page of 1 Zero-Index.
  5. The Fifth item, holding 4 as its Zero-Index, would be found at the 1 Zero-Index position, inside the page of 2 Zero-Index.
  6. And so on,…


This time you were able to do it manually as the items count is not that big, but, this is not always the case. Therefore, we need to analyze the example above and come up with some mathematical formulas.


Photo by Saad Ahmad on Unsplash

The Formula

Doing some analysis, we can come up with the following formula:


Image by Ahmed Tarek


Let me explain; when you divide the Item Zero-Index on the Page Size, you get two things:


  1. The result representing the Page Zero-Index.
  2. The remainder representing the Item Zero-Index Per Page.


Don’t you believe me? ok, I will show you…


Photo by Markus Winkler on Unsplash

Moment of Truth

Let’s apply the formula on our example and see where it goes from there.


The First (0) item, would be found at the position 0, inside page 0


The Second (1) item, would be found at the position 1, inside page 0


The Third (2) item, would be found at the position 2, inside page 0


The Fourth (3) item, would be found at the position 0, inside page 1


The Fifth (4) item, would be found at the position 1, inside page 1


The Sixth (5) item, would be found at the position 2, inside page 1


The Seventh (6) item, would be found at the position 0, inside page 2


The Eighth (7) item, would be found at the position 1, inside page 2


The Ninth (8) item, would be found at the position 2, inside page 2


The Tenth (9) item, would be found at the position 0, inside page 3


The Eleventh (10) item, would be found at the position 1, inside page 3


I think now you believe me. The formula is proved to be working as charm.


Photo by Firmbee.com on Unsplash

Further Analysis

Having the formula proven, let’s do some further analysis.


The formula could be transformed into the shape below:


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.


Again, still you don’t believe me?


To verify these equations, let’s apply on our example:

  • On the first page, (first item Zero-Index = 0 * 3 = 0) and (last item Zero-Index = (0 * 3) + (3–1) = 2)
  • On the second page, (first item Zero-Index = 1 * 3 = 3) and (last item Zero-Index = (1 * 3) + (3–1) = 5)
  • On the third page, (first item Zero-Index = 2 * 3 = 6) and (last item Zero-Index = (2 * 3) + (3–1) = 8)
  • On the fourth page, (first item Zero-Index = 3 * 3 = 9) and (last item Zero-Index = (3 * 3) + (3–1) = 11 which is greater than the max available item index (9), therefore, last item Zero-Index = 9)

Photo by Nubelson Fernandes on Unsplash

Let’s See Some Code

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#.


JavaScript Code

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))
			};
		}
	};
};


Now, executing this code:


let items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

let pagingResult = items.page(3);
console.log(pagingResult);


Would return:


Image by Ahmed Tarek


And, executing this code:


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 }


Would return:


Image by Ahmed Tarek


.NET C# Code

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
            )
        );
    }
}


Now, executing this code:


var items = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var pagingDescriptor = items.Page(3);


Would return:


Image by Ahmed Tarek


And, executing this code:


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}");


Would return:


Image by Ahmed Tarek


Photo by Grégoire Bertaud on Unsplash

Final Words

That’s it. These are the most important equations you would need to know about to apply paging in any situation.


You can also use the code samples to apply to your own project using whatever language or framework you are using.


That’s it, hope you found reading this article as interesting as I found writing it.


Also Published here