vb.net lamba表达式,用于选择较低值和较高值之间的所有值以及下一个较低值和较高值

时间:2010-11-19 16:48:39

标签: vb.net lambda

我需要一些lamda表达式的帮助来获取值范围的子集。我有一个较低和较高的值,并且它们之间的所有内容似乎都很容易,但我还需要包含下一个更高和更高的值。我可以分别做这些,但如果可能的话,我想一次性完成。

我需要子集的范围有150个值。一个小例子看起来像: {8.206,8.206,8.201,8.196,8.193,8.192,8.189,8.174,8.171,8.171,8.166,8.163,8.157,8.154,8.153,8.14,8.131}

我的较低值是:8.16 我的上限值是:8.17

我需要回来:{8.171,8.171,8.166,8.163,8.157}

2 个答案:

答案 0 :(得分:0)

在C#中有一个类似的VB等价物。这样的事情应该是(未经测试)

...

enum RangeRelation {Below, InRange, Above};

...

mySetOfNumbers    
.Select(number =>
  new {
    Number = number,
    RangeRelation = 
             number < lowerBound ? RangeRelation.Below : 
             number > upperBound ? RangeRelation.Above :
             RangeRelation.InRange
  })
  .GroupBy(x=>x.RangeRelation)
  .SelectMany(group =>
    group.Key == RangeRelation.Below ?  
       ( group.Any() ? new [] { group.OrderBy(x=>x).Last() } : new double[0] ) :
    group.Key == RangeRelation.Above ? 
       ( group.Any() ? new [] { group.OrderBy(x=>x).First() } : new double[0] ) :
    group
  );

如果对结果是否会被完全枚举存在一些疑问,这是可以的,因为延迟执行可能对您有利;但是,如果你肯定使用了所有结果值,我怀疑这将被编译为有效的东西。

也就是说,GroupBy()必须遍历集合一次,需要创建新类型,然后OrderBy()将类似 O(n * log n)以上和以下范围值的时间。这与以下内容相反:

double? above = null;
double? below = null;
var selected = new List<double>();
foreach(var number in mySetOfNumbers)
  if(number < lowerBound && number > below??Double.MinValue)
   below = number;
  else if(number > upperBound && number < above??Double.MaxValue)
   above = number;
  else
   selected.Add(number);

if(above != null) selected.Add(above);
if(below != null) selected.Add(below);

return selected;

只需要一次枚举。

有人说......对于150个值进行优化并不重要。

答案 1 :(得分:0)

我最终做了这样的事情:

Dim myData As New List(Of someData) 
myData = sorceData.Where(Function(i) i.somevalue >= myLowervalue And i.somevalue <= myUpperValue).ToList 
myData = myData.Concat(sorceData.Where(Function(i) i.somevalue > myUpperValue).Take(1).ToList).ToList 
myData = myData.Concat(sorceData.Where(Function(i) i.somevalue < myLowervalue ).Take(1).ToList).ToList 

这不是单一的表达,但它有效。