Вы находитесь на странице: 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

## 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))
{
{
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())))
{
}
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;
}

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

}
}
}

bool result;

## 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*/

## 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*/

## 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*/

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

};

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

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

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

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

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

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

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

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