重叠范围检查重叠



我有一个范围列表,我想找出它们是否重叠。

我有以下代码。这似乎不起作用。是否有一种更简单的方法来执行此操作或有效的方法:)

事先感谢您的任何建议。

   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; }
}

首先合并数字,然后检查生成的列表按顺序排序:

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

过去,我面临着一个挑战,我必须为用户创建的范围(整数或reals)编写验证算法。我不得不检查3件事:

  1. 范围是连续的
  2. 范围不是重叠
  3. 低值必须始终&lt; =远小于高

所以我想出了以下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

我们通过范围迭代并成对比较它们。对于我们:

  1. 找到重叠的范围并提出错误
  2. 查找Start&amp;反向终点并提出错误

如果以上都没有发生,我们计算终点的差异。该数字必须等于范围的数量减去步骤(1、0.1、0.01等)。否则我们提出了一个错误。

希望这会有所帮助!

您可以通过稍微修改rezaarabs答案来满足新要求:

rangeList
.Select(p => new[] { p.FromNumber, p.ToNumber })
.SelectMany(p => p.Distinct())
.Aggregate((p, q) => q >= p ? q : int.MaxValue) == int.MaxValue

解决此问题的解决方案就像编写自己的RangeList : IList<Range>一样简单,当指定范围与集合中的一个或多个范围重叠时,其Add()方法会引发异常。p>工作示例:

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
}

用法:

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);
}

相关内容

  • 没有找到相关文章

最新更新