I have a situation that is well explained 开发者_StackOverflow中文版in this question:
Range intersection / union
I need a C# implementation (a collection maybe) that takes a list of ranges (of ints) and do the union of them. Then I need to iterate through all ints in this collection (also numbers between ranges) Are there any library/implementation so that I don't have to rewrite everything by myself?
You might take a look at this implementation and see if it will fit your needs.
Combine ranges with Range.Coalesce
:
var range1 = Range.Create(0, 5, "Range 1");
var range2 = Range.Create(11, 41, "Range 2");
var range3 = Range.Create(34, 50, "Range 3");
var ranges = new List<Range> { range1, range2, range3 };
var unioned = Range.Coalesce(ranges);
Iterate over ranges with .Iterate
:
foreach (var range in unioned)
{
foreach (int i in range.Iterate(x => x + 1))
{
Debug.WriteLine(i);
}
}
The simplest thing that comes to my mind is to use Enumerable.Range, and then treat the different IEnumerable with standard linq operators. Something like:
var list = Enumerable.Range(1, 5)
.Concat(Enumerable.Range(7, 11))
.Concat(Enumerable.Range(13, 22))
foreach(var number in list)
// Do something
Obviously you can use Union and Intersect as well... clearly you can also put your ranges in a List<IEnumerable<int>>
or something similar and then iterate over the elements for producing a single list of the elements:
var ranges = new List<IEnumerable<int>>
{
Enumerable.Range(1, 5),
Enumerable.Range(7, 11),
Enumerable.Range(10, 22)
};
var unionOfRanges = Enumerable.Empty<int>();
foreach(var range in ranges)
unionOfRanges = unionOfRanges.Union(range);
foreach(var item in unionOfRanges)
// Do something
The following is vanilla Linq implementation:
var r1 = Enumerable.Range(1,10);
var r2 = Enumerable.Range(20,5);
var r3 = Enumerable.Range(-5,10);
var union = r1.Union(r2).Union(r3).Distinct();
foreach(var n in union.OrderBy(n=>n))
Console.WriteLine(n);
System.Collections.Generic.HashSet has just the thing:
UnionWith( IEnumerable<T> other )
. Modifies the current HashSet object to contain all elements that are present in itself, the specified collection, or both.IntersectWith( IEnumerable<T> other )
. Modifies the current HashSet object to contain only elements that are present in that object and in the specified collection.
The data structure you are looking for is called an "interval tree".
You can find different implementations on the net.
For example here's one: http://www.emilstefanov.net/Projects/RangeSearchTree.aspx
精彩评论