我需要一些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}
答案 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
这不是单一的表达,但它有效。