[英]Overlapping Ranges Check for Overlapping
I have a list of ranges and I would like to find out if they overlap. 我有一个范围列表,我想知道它们是否重叠。
I have the following code. 我有以下代码。 Which does not seem to be working.
哪个似乎没有用。 Is there an easier way to do this or a way that works :)
有没有更简单的方法来做到这一点或工作的方式:)
Thanks in advance for any advice. 提前感谢任何建议。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private IList<Range> rangeList;
private void Form1_Load(object sender, EventArgs e)
{
rangeList.Add(new Range{FromNumber = 0, ToNumber = 100});
rangeList.Add(new Range { FromNumber = 101, ToNumber = 200 });
// this range should over lap and throw an exception
rangeList.Add(new Range { FromNumber = 199, ToNumber = 300 });
}
private bool RangesOverlap()
{
var bigList = new List<List<int>>();
foreach (var range in this.rangeList)
{
bigList.Add(new List<int> { range.FromNumber , range.ToNumber });
}
IEnumerable<IEnumerable<int>> lists = bigList;
return lists
.Where(c => c != null && c.Any())
.Aggregate(Enumerable.Intersect)
.ToList().Count > 0;
}
}
public class Range
{
public int FromNumber { get; set; }
public int ToNumber { get; set; }
}
First merge numbers and then check generated list is in sorted order: 首先合并数字然后检查生成的列表是按排序顺序:
rangeList
.OrderBy(p => p.FromNumber)
.Select(p => new[] { p.FromNumber, p.ToNumber })
.SelectMany(p => p)
.Aggregate((p, q) => q >= p ? q : int.MaxValue) == int.MaxValue
In the past I faced a challenge where I had to write a validating algorithm for ranges that are created by the user (integers or reals). 在过去,我遇到了一个挑战,我必须为用户创建的范围(整数或实数)编写验证算法。 I had to check 3 things:
我必须检查3件事:
So I came up with the following PHP algorithm. 所以我提出了以下PHP算法。
//Let's hardcode an array of integers (it can be of reals as well):
$range = array
(
array(1, 13),
array(14, 20),
array(21, 45),
array(46, 50),
array(51, 60)
);
//And the validation algorithm:
$j = 0;
$rows = sizeof($range);
$step = 1; // This indicates the step of the values.
// 1 for integers, 0.1 or 0.01 for reals
for ($x=0; $x<$rows; $x++)
for ($y=0; $y<$rows; $y++) {
if ( ($range[$x][0] <= $range[$y][0]) AND ($range[$y][0] <= $range[$x][1]) AND ($x != $y) ) {
echo "Ranges intercepting"; // replace with error handling code
break 3;
}
if ( $range[$x][0] > $range[$x][1] ) {
echo "Not valid high & low"; // replace with error handling code
break 3;
}
if ( $range[$x][0] - $range[$y][1] == $step ) {
$j++;
}
}
if ( $j != $rows - $step )
echo "Not continuous"; // replace with error handling code
We iterate through the ranges and compare them in pairs. 我们遍历范围并成对比较它们。 For each pair we:
对于每一对我们:
If none of the above occurs, we count the difference of end - start points. 如果没有上述情况发生,我们计算结束起点的差异。 This number must be equals to the number of ranges minus the step (1, 0.1, 0.01, etc).
此数字必须等于范围数减去步骤(1,0.1,0.01等)。 Otherwise we raise an error.
否则我们会引发错误。
Hope this helps! 希望这可以帮助!
You can fulfill your new requirement with a slight modification of RezaArabs answer: 您可以通过略微修改RezaArabs答案来满足您的新要求:
rangeList
.Select(p => new[] { p.FromNumber, p.ToNumber })
.SelectMany(p => p.Distinct())
.Aggregate((p, q) => q >= p ? q : int.MaxValue) == int.MaxValue
The solution to this problem can be as simple as writing your own RangeList : IList<Range>
whose Add()
method throws an exception when the specified range overlaps with one or more ranges that are already in the collection. 解决此问题的方法可以像编写自己的
RangeList : IList<Range>
一样简单RangeList : IList<Range>
,当指定范围与集合中已有的一个或多个范围重叠时,其Add()
方法会引发异常。
Working example: 工作范例:
class Range
{
public int FromNumber { get; set; }
public int ToNumber { get; set; }
public bool Intersects(Range range)
{
if ( this.FromNumber <= range.ToNumber )
{
return (this.ToNumber >= range.FromNumber);
}
else if ( this.ToNumber >= range.FromNumber )
{
return (this.FromNumber <= range.ToNumber);
}
return false;
}
}
class RangeList : IList<Range>
{
private readonly IList<Range> innerList;
#region Constructors
public RangeList()
{
this.innerList = new List<Range>();
}
public RangeList(int capacity)
{
this.innerList = new List<Range>(capacity);
}
public RangeList(IEnumerable<Range> collection)
{
if ( collection == null )
throw new ArgumentNullException("collection");
var overlap = from left in collection
from right in collection.SkipWhile(right => left != right)
where left != right
select left.Intersects(right);
if ( overlap.SkipWhile(value => value == false).Any() )
throw new ArgumentOutOfRangeException("collection", "The specified collection contains overlapping ranges.");
this.innerList = new List<Range>(collection);
}
#endregion
private bool IsUniqueRange(Range range)
{
if ( range == null )
throw new ArgumentNullException("range");
return !(this.innerList.Any(range.Intersects));
}
private Range EnsureUniqueRange(Range range)
{
if ( !IsUniqueRange(range) )
{
throw new ArgumentOutOfRangeException("range", "The specified range overlaps with one or more other ranges in this collection.");
}
return range;
}
public Range this[int index]
{
get
{
return this.innerList[index];
}
set
{
this.innerList[index] = EnsureUniqueRange(value);
}
}
public void Insert(int index, Range item)
{
this.innerList.Insert(index, EnsureUniqueRange(item));
}
public void Add(Range item)
{
this.innerList.Add(EnsureUniqueRange(item));
}
#region Remaining implementation details
public int IndexOf(Range item)
{
return this.innerList.IndexOf(item);
}
public void RemoveAt(int index)
{
this.innerList.RemoveAt(index);
}
public void Clear()
{
this.innerList.Clear();
}
public bool Contains(Range item)
{
return this.innerList.Contains(item);
}
public void CopyTo(Range[] array, int arrayIndex)
{
this.innerList.CopyTo(array, arrayIndex);
}
public int Count
{
get { return this.innerList.Count; }
}
public bool IsReadOnly
{
get { return this.innerList.IsReadOnly; }
}
public bool Remove(Range item)
{
return this.innerList.Remove(item);
}
public IEnumerator<Range> GetEnumerator()
{
return this.innerList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.innerList.GetEnumerator();
}
#endregion
}
Usage: 用法:
IList<Range> rangeList = new RangeList();
try
{
rangeList.Add(new Range { FromNumber = 12, ToNumber = 12 });
rangeList.Add(new Range { FromNumber = 13, ToNumber = 20 }); // should NOT overlap
rangeList.Add(new Range { FromNumber = 12, ToNumber = 20 }); // should overlap
}
catch ( ArgumentOutOfRangeException exception )
{
Console.WriteLine(exception.Message);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.