首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从没有间隙的对象列表中获取范围:

从没有间隙的对象列表中获取范围:
EN

Stack Overflow用户
提问于 2013-10-30 07:37:29
回答 1查看 94关注 0票数 0

给出一个列表,列表中有数千个对象,如下所示:

代码语言:javascript
运行
复制
 var list = new List<PointAddress>();
 list.Add(new PointAddress { Line = 1, Number = 100f });
 list.Add(new PointAddress { Line = 1, Number = 101f });
 list.Add(new PointAddress { Line = 1, Number = 105f });
 list.Add(new PointAddress { Line = 1, Number = 106f });
 list.Add(new PointAddress { Line = 2, Number = 103f });
 list.Add(new PointAddress { Line = 2, Number = 104f });

创建无间隔范围的最佳方法是什么(基于数字属性),如下所示?如果Number属性的差异>1,那么它是一个间隙,Number应该在不同的组中。

组1

线路= 1,编号= 100f

线路= 1,编号= 101f

第二组

行= 1,编号= 105f

线路= 1,编号= 106f

第三组

线路= 2,编号= 103f

线路= 2,编号= 104f

基本上,如果Gap >1,那么它应该按Line在不同的组中。

如果这条线不同,那么它就是一个不同的组。如果Number是相邻的number,而Line是相同的,那么它必须在相同的组中,如示例中所示。线路1被分成两组-组1和组2,因为数字不相邻。

EN

回答 1

Stack Overflow用户

发布于 2013-10-30 08:37:24

假设您的列表是有序的,下面这样的代码应该是有效的。

首先,使用一个简单的通用Linq扩展对列表进行分区:

代码语言:javascript
运行
复制
public static IEnumerable<List<T>> Partition<T>( this IEnumerable<T> source , Func<T,T,bool> areAdjacent )
{
  List<T> list = null ;
  T       prev = default(T) ;

  foreach ( T curr in source )
  {
    if ( list == null )
    {
      list = new List<T> {curr} ;
    }
    else if ( areAdjacent(prev,curr) )
    {
      list.Add(curr) ;
    }
    else
    {
      yield return list ;
      list = new List<T> {curr} ;
    }

    prev = curr ;
  }

  if ( list != null )
  {
    yield return list ;
  }

}

然后,您可以这样调用它

代码语言:javascript
运行
复制
List<PointAddress> addressList = GetSomeEnormousList() ;

List<List<PointAddress>> ranges = addressList
                                  .Partition( (prev,curr) => curr.Line == prev.Line && curr.Number - prev.Number == 1.0 )
                                  .ToList()
                                  ;

您所需要的只是一个lambda,它将接受两个PointAddress项,并对它们进行比较,以确定是否存在序列中断,如果这两个项被认为是相邻的,则返回true,如果不相邻,则返回false。如何确定有序集合中两个项目的顺序和邻接关系取决于您。

如果您的列表是无序的,您可以对其进行排序:

代码语言:javascript
运行
复制
List<List<PointAddress>> ranges = addressList
                                  .OrderBy( x => x.Line )
                                  .ThenBy( x => x.Number )
                                  .Partition( (prev,curr) => curr.Line == prev.Line && curr.Number - prev.Number == 1.0 )
                                  .ToList() ;

简单!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19671181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档