В 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 * logn) время для значений диапазона выше и ниже.Это в отличие от чего-то подобного:
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 значений оптимизация вообще не имеет значения.