C# 区间合并(Linq To Sql)

来源:互联网 发布:https 隐藏index.php 编辑:程序博客网 时间:2024/06/12 01:22

一、项目问题

       C#的list<point>类型中存入了很多区间类似于(a--b),Point.x存入的是开始位置,Point.Y存入的是结束位置。list<point>中存入了很多这样的

点,例如1--4,3---8,9--20,17--25。

而目前的问题是要把这些重合的区间从新合并成多个区间,例如上边四个区间应该合并为:1--8和9--25 。最后的list<point>类型中应该没有再重复的区间。

二、LInq方面的解决方案(一高手提供)

[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace ConsoleApplication1  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             List<Point> data = new List<Point>()  
  13.             {  
  14.                 new Point() { X = 1, Y = 4 },  
  15.                 new Point() { X = 3, Y = 8 },  
  16.                 new Point() { X = 9, Y = 20 },  
  17.                 new Point() { X = 17, Y = 25 }  
  18.             };  
  19.             data.ForEach(x =>  
  20.             {  
  21.                 if (data.Where(y => y != x).Any(y => y.X <= x.Y && y.Y >= x.X))  
  22.                 {  
  23.                     var desc = data.Where(y => y != x).First(y => y.X <= x.Y && y.Y >= x.X);//返回除自己以外的满足条件的区间  
  24.                     x.X = desc.X > x.X ? x.X : desc.X;  
  25.                     x.Y = desc.Y > x.Y ? desc.Y : x.Y;  
  26.                 }  
  27.             });  
  28.             data = data.GroupBy(x => new { x.X, x.Y }).Select(x => new Point() { X = x.Key.X, Y = x.Key.Y }).ToList();//合并list<point>中重复的区间  
  29.             foreach (var item in data)  
  30.             {  
  31.                 Console.WriteLine(item);  
  32.             }  
  33.         }  
  34.     }  
  35.     class Point  
  36.     {  
  37.         public int X { getset; }  
  38.         public int Y { getset; }  
  39.         public override string ToString()  
  40.         {  
  41.             return string.Format("X = {0}, Y = {1}.", X, Y);  
  42.         }  
  43.     }  
  44. }  

     上面的代码输出为:1--8和9--25.

三、非Ling to Sql的解决方案(一)

         因为我自己的版本面向的.Net FrameWork版本是2.0的,而只有3.5的.net FrameWork版本才支持Linq,所以我按照上面的办法写了跟上述功能相似的犯法,类似于Where和Group的用法,经过自己的测试达到了上述的要求,代码如下:

[csharp] view plaincopyprint?
  1.     List<PointA> data = new List<PointA>   
  2.     {   
  3.     new PointA() { X = 18,Y = 26},  
  4.             new PointA() { X = 3, Y = 8 },  
  5.             new PointA() { X = 1, Y = 4 },  
  6.             new PointA() { X = 9, Y = 20 },  
  7.             new PointA() { X = 17, Y = 25 }  
  8.     };  
  9.     public void sort(List<PointA> data)  
  10.     {  
  11.         data.ForEach(x => {  
  12.             PointA temp = new PointA();  
  13.             temp = innerSort(data, x);//返回第一个满足条件的PontA类  
  14.             if (0!=temp.X && 0!=temp.Y)  
  15.             {  
  16.                 x.X = temp.X > x.X ? x.X : temp.X;  
  17.                 x.Y = temp.Y > x.Y ? temp.Y : x.Y;  
  18.             }  
  19.         });  
  20.         /*删除重复数据*/  
  21.         for (int i = 0; i < data.Count - 1; i++)  
  22.         {  
  23.             for (int j = data.Count - 1; j > i; j--)  
  24.             {  
  25.                 if (data[j].X==data[i].X &&data[j].Y==data[i].Y)  
  26.                 {  
  27.                     data.Remove(data[j]);  
  28.                 }  
  29.             }  
  30.         }  
  31.         Console.WriteLine(data);  
  32.     }  
  33.     /*此方法用来返回第一个满足条件的PointA的区间*/  
  34.   private PointA innerSort(List<PointA> list,PointA x)  
  35.     {  
  36.     PointA result = new PointA();  
  37.     foreach (PointA y in list)  
  38.     {  
  39.         if (y != x && y.X <= x.Y && y.Y >= x.X)  
  40.         {  
  41.             result = y;  
  42.             break;  
  43.         }  
  44.     }  
  45.     return result;  
  46.     }  
  47. }  
  48. class PointA  
  49. {  
  50.     public int X { getset; }  
  51.     public int Y { getset; }  
  52.     public override string ToString()  
  53.     {  
  54.         return string.Format("X = {0}, Y = {1}.", X, Y);  
  55.     }  

四、非Linq解决方案(二)

         上边的两个方法只能合并区间相邻的时候,比如(1,4)、(2、8),会输出(1,8),但是当输入(1,4)、(8,15)、(2,10)的时候输出结果是(1,10)、(8,15),显然结果是不正确的,所以自己又改进了以前的方法,如下所示:

[csharp] view plaincopyprint?
  1. List<PointA> data = new List<PointA>   
  2.         {   
  3.         new PointA() { X = 18,Y = 26},  
  4.                 new PointA() { X = 3, Y = 8 },  
  5.                 new PointA() { X = 1, Y = 4 },  
  6.                 new PointA() { X = 9, Y = 20 },  
  7.                 new PointA() { X = 17, Y = 25 }  
  8.         };  
  9.         /// <summary>  
  10.         /// 双重循环的合并算法,实现了任意多个区间的合并  
  11.         /// 思路:外循环,从第一个到最后一个  
  12.         /// 内循环,找到符合合并条件的选项,将合并后的数据保存在data[i-1]中,然后删除已经被合并的  
  13.         /// 数据,同时将内循环的m初始化0,从新开始下一轮的循环,m!=i-1是为了限定在相等的时候不要  
  14.         /// 删除数据  
  15.         /// </summary>  
  16.         /// <param name="data"></param>  
  17.         public void SortTest(List<PointF> data)  
  18.         {  
  19.             for (int i = 1; i < data.Count; i++)  
  20.             {  
  21.                 for (int m = i; m < data.Count; m++)  
  22.                 {  
  23.                     if (data[m].X <= data[i-1].Y && data[m].Y >= data[i-1].X &&m!=i-1)  
  24.                     {  
  25.                         PointF tempPoint = new PointF();  
  26.                         tempPoint.X = data[i-1].X > data[m].X ? data[m].X : data[i-1].X;  
  27.                         tempPoint.Y = data[i-1].Y > data[m].Y ? data[i-1].Y : data[m].Y;  
  28.                         data[i-1] = tempPoint;//结构体是值传递,要修改只能通过这种方式  
  29.                         data.Remove(data[m]);  
  30.                         m = 0;//从头开始此次循环合并  
  31.                     }  
  32.                 }  
  33.             }  
  34.         }  
  35.   
  36.     }  
  37.     class PointA  
  38.     {  
  39.         public int X { getset; }  
  40.         public int Y { getset; }  
  41.         public override string ToString()  
  42.         {  
  43.             return string.Format("X = {0}, Y = {1}.", X, Y);  

  1.         }  

五、总结

      从这个例子可以看出使用Linq To Sql可以使程序的代码量大大减少,并且效率也很高。


0 0
原创粉丝点击