Вы находитесь на странице: 1из 6

02/06/2019 C#: Integer Range Helper - CodeProject

C#: Integer Range Helper


DiponRoy, 2 Jun 2019

Utility class and model to manage range related operations

RangeHelper_Integer.zip - 5.6 KB

Introduction
By default in C#, we have Enumerable.Range(Int32, Int32) which generates a sequence of integral numbers within a specified range.
Here is this article we are going to explore a few more options to extend the range related operations.

Background
What are we going to do?

Create a model, which will

Define a range.
Check if an item inside the range
Check if a range inside the range
Check if a range overlapping the range

Create a utility class

Populating items of the range


List to sequence ranges
List to sequence range string list specifying the start and end item
Find overlapping items in input subranges
Find missing items in input subranges
Find unknown items in input subranges

Range Model
Here is our range model

public class IntegerRangeModel


{
public int StartFrom { get; set; }
public int EndTo { get; set; }

public IntegerRangeModel(int startFrom, int endTo)


{
StartFrom = startFrom;
EndTo = endTo;
}
https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-Helper?display=Print 1/6
02/06/2019 C#: Integer Range Helper - CodeProject

public bool Includes(int value)


{
bool includes = StartFrom <= value && value <= EndTo;
return includes;
}

public bool Includes(IntegerRangeModel range)


{
bool includes = Includes(range.StartFrom) && Includes(range.EndTo);
return includes;
}

/*https://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap*/
public bool Overlappes(IntegerRangeModel range)
{
bool includes = false;
includes = StartFrom <= range.EndTo && EndTo >= range.StartFrom; /*(StartA <= EndB)
and(EndA >= StartB)*/
//includes = Includes(range.StartFrom) || Includes(range.EndTo); /*can also use this
one*/
return includes;
}
}

Utility Class
Using the range model in the utility class

using System;
using System.Collections.Generic;
using System.Linq;

public class IntegerRangeUtility


{
private static IEnumerable<int> Range(int start, int end)
{
if (start > end)
{
throw new ArgumentException("Range end should be greater than range start");
}
int count = end - start + 1;
return Enumerable.Range(start, count);
}

public static IEnumerable<int> Range(IntegerRangeModel model)


{
int start = model.StartFrom;
int end = model.EndTo;
return Range(start, end);
}

/*
* missing, overlapping
* https://stackoverflow.com/questions/7024051/find-missing-and-overlapping-numbers-in-
sequences
*/
public static IEnumerable<int> Overlappings(IEnumerable<int> expectedRangeItems,
IEnumerable<IntegerRangeModel> sourceRanges)
{
IEnumerable<int> overlapping = expectedRangeItems.Where(i => sourceRanges.Count(t =>
t.StartFrom <= i && t.EndTo >= i) > 1);
return overlapping;
}

public static IEnumerable<int> Missings(IEnumerable<int> expectedRangeItems,

https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-Helper?display=Print 2/6
02/06/2019 C#: Integer Range Helper - CodeProject

IEnumerable<IntegerRangeModel> sourceRanges)
{
IEnumerable<int> missing = expectedRangeItems.Where(i => sourceRanges.All(t =>
t.StartFrom > i || t.EndTo < i));
return missing;
}

public static IEnumerable<int> Unknowns(IEnumerable<int> expectedRangeItems,


IEnumerable<IntegerRangeModel> sourceRanges)
{
HashSet<int> hash = new HashSet<int>();
foreach (var sourceRange in sourceRanges.OrderBy(x => x.StartFrom))
{
foreach (var item in Range(sourceRange.StartFrom, sourceRange.EndTo))
{
if (!expectedRangeItems.Contains(item))
{
if (hash.Add(item))
{
yield return item;
}
}
}
}
}

/*
* https://stackoverflow.com/questions/19576504/find-available-numbers-from-a-list-of-
numbers-in-a-particular-range
* https://stackoverflow.com/questions/4936876/grouping-into-ranges-of-continuous-
integers/4937283#4937283
*/
public static IEnumerable<List<T>> ToContiguousSequences<T>(IEnumerable<T> sequence,
Func<T, T> next)
{
sequence = sequence.OrderBy(x => x);
var e = sequence.GetEnumerator();
if (!e.MoveNext())
{
throw new InvalidOperationException("Sequence is empty.");
}
var currentList = new List<T> { e.Current };
while (e.MoveNext())
{
T current = e.Current;
if (current.Equals(next(currentList.Last())))
{
currentList.Add(current);
}
else
{
yield return currentList;
currentList = new List<T> { current };
}
}
yield return currentList;
}

public static IEnumerable<List<int>> ToContiguousSequences(IEnumerable<int> source)


{
Func<int, int> nextFunc = n => n + 1;
return ToContiguousSequences(source, nextFunc);
}

public static IEnumerable<string> ToRangesString(IEnumerable<int> source)


{
foreach (var sequence in ToContiguousSequences(source))
{
string rangeString = String.Format(@"{0}-{1}", sequence.First(), sequence.Last());

https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-Helper?display=Print 3/6
02/06/2019 C#: Integer Range Helper - CodeProject

yield return rangeString;


}
}
}

Using The Range Model

Define an expected range

var intRange = new IntegerRangeModel(1, 100);


bool result;

Check if an item in the range

result = intRange.Includes(0); /*false*/


result = intRange.Includes(1); /*true*/
result = intRange.Includes(100); /*true*/
result = intRange.Includes(50); /*true*/
result = intRange.Includes(101); /*false*/

Check if a range in the range

result = intRange.Includes(new IntegerRangeModel(-10, 10)); /*false*/


result = intRange.Includes(new IntegerRangeModel(1, 100)); /*true*/
result = intRange.Includes(new IntegerRangeModel(2, 99)); /*true*/
result = intRange.Includes(new IntegerRangeModel(90, 110)); /*false*/

Check if a range overlapping the range

result = intRange.Overlappes(new IntegerRangeModel(-20, -10)); /*false*/


result = intRange.Overlappes(new IntegerRangeModel(-10, 10)); /*true*/
result = intRange.Overlappes(new IntegerRangeModel(1, 100)); /*true*/
result = intRange.Overlappes(new IntegerRangeModel(2, 99)); /*true*/
result = intRange.Overlappes(new IntegerRangeModel(90, 110)); /*true*/
result = intRange.Overlappes(new IntegerRangeModel(101, 110)); /*false*/

Let's get started with the utility class.

Using The Utility Class


var expectedRange = new IntegerRangeModel(1, 100); /*target range 1-100*/
var inputSubRanges = new List<IntegerRangeModel>()
{
new IntegerRangeModel(-10, 0), /*unknown: -10-0 will not appear in overlapping*/
new IntegerRangeModel(-10, 0), /*unknown: -10-0*/
new IntegerRangeModel(1, 10), /*overlapping 5-10*/
new IntegerRangeModel(5, 15), /*overlapping 5-10*/
//new IntegerRangeModel(16, 30), /*missing 16-30*/
new IntegerRangeModel(31, 40), /*overlapping 31-40*/
new IntegerRangeModel(31, 40), /*overlapping 31-40*/
new IntegerRangeModel(41, 70),
//new IntegerRangeModel(71, 80), /*missing 71-80*/
new IntegerRangeModel(81, 100),
new IntegerRangeModel(101, 115), /*unknown: 101-120*/

https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-Helper?display=Print 4/6
02/06/2019 C#: Integer Range Helper - CodeProject

new IntegerRangeModel(105, 120), /*unknown: 101-120 will not appear in overlapping*/


};

Populating a range of items

List<int> range = IntegerRangeUtility.Range(expectedRange).ToList();

List to sequence ranges

List<List<int>> ranges = IntegerRangeUtility.ToContiguousSequences(range).ToList();

List to sequence range string list specifying the start and end item

List<string> rangeStrings = IntegerRangeUtility.ToRangesString(range).ToList();

Find overlapping items in input subranges

List<int> overlappings = IntegerRangeUtility.Overlappings(range, inputSubRanges).ToList();


List<string> overlappingRangeStrings =
IntegerRangeUtility.ToRangesString(overlappings).ToList();

Find missing items in input subranges

List<int> missings = IntegerRangeUtility.Missings(range, inputSubRanges).ToList();


List<string> missingRangeStrings = IntegerRangeUtility.ToRangesString(missings).ToList();

Find unknown items in input subranges

List<int> unkowns = IntegerRangeUtility.Unknowns(range, inputSubRanges).ToList();


List<string> unkownRangeStrings = IntegerRangeUtility.ToRangesString(unkowns).ToList();

Future Improvements
1. Move range population option to the model class and use lazyloading. 
2. Creating a generic utility class to manage different types like DateTime, double or any user-defined type.

Please find Visual Studio 2017 solution as an attachment.

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-Helper?display=Print 5/6
02/06/2019 C#: Integer Range Helper - CodeProject

DiponRoy No Biography provided


Bangladesh

Comments and Discussions


0 messages have been posted for this article Visit https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-
Helper to post and view comments on this article, or click here to get a print view with messages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2019 by DiponRoy
Web06 | 2.8.190530.2 | Last Updated 2 Jun 2019 Everything else Copyright © CodeProject, 1999-2019

https://www.codeproject.com/Tips/5061316/Csharp-Integer-Range-Helper?display=Print 6/6