C# 具有属性的可能相交范围列表的清理算法
我有这些对象的范围和属性列表。我的目标是获取这些对象的列表,并创建一个没有范围重叠的新列表。当两个范围重叠时,重叠区域可以替换为具有特性并集的对象。我希望图片能比文字更好地解释这一点 范围的解开C# 具有属性的可能相交范围列表的清理算法,c#,list,range,C#,List,Range,我有这些对象的范围和属性列表。我的目标是获取这些对象的列表,并创建一个没有范围重叠的新列表。当两个范围重叠时,重叠区域可以替换为具有特性并集的对象。我希望图片能比文字更好地解释这一点 范围的解开 我能够用下面的代码实现这一点,但是它相当笨拙,并且使用了我试图避免的goto。此代码背后的方法是比较每对范围,如果存在交叉点,则将两个RangeObjects替换为最多三个RangeObjects: 一个用于与rangeObject2不相交的rangeObject1部分 一个用于与rangeObje
我能够用下面的代码实现这一点,但是它相当笨拙,并且使用了我试图避免的goto。此代码背后的方法是比较每对范围,如果存在交叉点,则将两个RangeObjects替换为最多三个RangeObjects:
- 一个用于与rangeObject2不相交的rangeObject1部分
- 一个用于与rangeObject1不相交的rangeObject2部分
- 一个用于rangeObject1和rangeObject2与联合属性的交集
类范围对象
{
RangeObject(int开始、int结束、列表属性)
{
开始=开始;
结束=结束;
属性=属性;
}
public int Start{get;set;}
公共int End{get;set;}
公共整数长度{get=>End-Start;}
公共列表属性{get;}
公共布尔值IsInRange(int值)
{
返回值>开始值和结束值rangeObject2.Start | |((rangeObject1.Start==rangeObject2.Start)&&(rangeObject1.Length>rangeObject2.Length)))
{
RangeObject temp=rangeObject1;
rangeObject1=rangeObject2;
rangeObject2=温度;
}
如果(rangeObject1.Start==rangeObject2.Start&&rangeObject1.End==rangeObject2.End)//范围相等
{
result.Add(新建RangeObject(rangeObject1.Start,rangeObject1.End,rangeObject1.Properties.Union(rangeObject2.Properties.ToList());//返回一个联合属性的RangeObject
}
else if(rangeObject1.IsInRange(rangeObject2.Start)&&rangeObject1.IsInRange(rangeObject2.End))//Range1中包含的Range2
{
if(rangeObject1.Start!=rangeObject2.Start)
{
添加(新的RangeObject(rangeObject1.Start,rangeObject2.Start-rangeObject1.Start,rangeObject1.Properties));
}
添加(新的RangeObject(rangeObject2.Start,rangeObject2.Length,rangeObject1.Properties.Union(rangeObject2.Properties.ToList());
if(rangeObject1.End!=rangeObject2.End)
{
添加(新的RangeObject(rangeObject2.End,rangeObject1.End-rangeObject2.End,rangeObject1.Properties));
}
}
else if(rangeObject1.IsInRange(rangeObject2.Start))//Range1中包含的Range2.Start
{
添加(新的RangeObject(rangeObject1.Start,rangeObject2.Start-rangeObject1.Start,rangeObject1.Properties));
添加(新的RangeObject(rangeObject2.Start,rangeObject1.End-rangeObject2.Start,rangeObject1.Properties.Union(rangeObject2.Properties.ToList());
添加(新的RangeObject(rangeObject1.End,rangeObject2.End-rangeObject1.End,rangeObject2.Properties));
}
否则//没有交叉口,不应该发生
{
结果。添加(rangeObject1);
结果。添加(rangeObject2);
}
返回结果;
}
}
关于如何更优雅地实现这一点,有什么想法吗?或者至少避免开始,因为当我切割范围时,我最终会将它们重新定位到末尾,并更改列表的长度/顺序,因此很难判断我比较了哪些范围。以下是一种摆脱“转到”的方法:
私有列表解开范围列表(列表列表)
{
列表1=新列表(列表);
list1.Sort();
int start=0;
而(!CheckSomething(list1,ref start));
list1.Sort();
返回列表1;
}
私有bool CheckSomething(列表列表1,ref int start)
{
for(int i=start;i
为了简单起见,我首先得到一个足够大的范围,以包括所有其他范围,但带有一个空的Properties
字段。这是通过获取所有范围的最小值和最大值来实现的
然后,我将一个接一个的范围与所谓的untangl结合起来