Build array index ranges of an integer in C# .NET

Suppose that we have a large array of data heavy objects that are impractical to handle in a single go. Instead we can read batches of the array until all elements have been processed. It can then be useful to build a range of indexes for the objects in the array that we want to extract.

E.g. if an array consists of 357 objects and we want to read at most 100 elements from it in a single batch then the size of the batches will be as follows:

100
100
100
57

…and we want to extract the elements by their indexes as follows:

0, 99
100, 199
200, 299
300, 356

…where the first number is the array start index and the second number is the array end index. Since we’re talking about array indexes the numbers are 0-based of course.

The first function we’ll need has been discussed in this post. It constructs the batch sizes as listed above 100, 100, 100 and 57:

private IEnumerable<int> BatchInteger(int total, int batchSize)
{
	if (batchSize == 0)
	{
		yield return 0;
	}

	if (batchSize >= total)
	{
		yield return total;
	}
	else
	{
		int rest = total % batchSize;
		int divided = total / batchSize;
		if (rest > 0)
		{
			divided += 1;
		}

		for (int i = 0; i < divided; i++)
		{
			if (rest > 0 && i == divided - 1)
			{
				yield return rest;
			}
			else
			{
				yield return batchSize;
			}
		}
	}
}

The start and end indexes could be stored in an object with two integer properties but for simplicity we can also return Tuples of two integers. The first integer will be the start index and the second integer will be the end index.

The following function will produce this range:

private List<Tuple<int, int>> GetArrayStartAndEndIndexes(int totalSize, int batchSize)
{
	List<int> groups = BatchInteger(totalSize, batchSize).ToList();
	List<Tuple<int, int>> arrayStartAndEndIndexes = new List<Tuple<int, int>>();
	for (int i = 0; i < groups.Count; i++)
	{
		if (i == 0)
		{
			arrayStartAndEndIndexes.Add(new Tuple<int, int>(0, groups[i] - 1));
		}
		else if (i == groups.Count - 1)
		{
			arrayStartAndEndIndexes.Add(new Tuple<int, int>(groups[i - 1] + ((i - 1) * batchSize), totalSize - 1));
		}
		else
		{
			arrayStartAndEndIndexes.Add(new Tuple<int, int>(groups[i - 1] + ((i - 1) * batchSize), groups[i - 1] + (i * batchSize) - 1));
		}
	}

	return arrayStartAndEndIndexes;
}

It accepts a total size and a batch. In our example they will be 357 and 100. The function first calls BatchInteger to build the range sizes. For each item in the “groups” integer list we build an element for the Tuple. The first element will always have 0 as the start index and group size – 1 as the end index. All the decrements by one you see in the function are due to array indexing.

Usage:

var startAndEndIndexesOfArray = this.GetArrayStartAndEndIndexes(357, 100);
foreach (var range in startAndEndIndexesOfArray)
{
	Console.WriteLine(string.Concat("Start: ", range.Item1, ", end: ", range.Item2));
}

Here’s the printout:

Start: 0, end: 99
Start: 100, end: 199
Start: 200, end: 299
Start: 300, end: 356

Another function that processes the large array can use these index numbers to extract the necessary subarrays.

View all various C# language feature related posts here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: